jQuery概览
前言
作为一个前端工程师,jQuery肯定是个十分熟悉的工具,可以说是入门级框架。因此读懂jQuery并且理解其架构思想,对于一个初中级工程师来说,成长很大。jQuery经过这么多年的架构演变,版本也从1.x升级到了2.x,其中不乏很多设计精髓。它的API设计的很巧妙,使得很多新手可以不了解原生的JS条件下,完成一些常见的交互。前端很重要的一部分就是DOM操作,jQuery秉承其 The Write Less, Do More 的理念,将复杂的DOM操作封装出简单易用的API。 本文选择的版本是2.1.1
外层沙箱
沙箱是前端中很常见的一种方式。jQuery中,为了避免全局变量的污染,将代码放入一个自执行的函数中,然后暴露出命名空间。
(function( global, factory ){
if( typeof module === "object" && typeof module.exports === "object" ){
module.exports = global.document ? factory( global, true ) : function(){}
}else{
factory( global );
}
}(window, function(){
if( typeof noGlobal === strundefined ){
window.jQuery = window.$ = jQuery;
}
return jQuery;
}))
jQuery的对象创建
jQuery没有使用正常的new来实例化出一个对象,而是调用其函数$(),真正实例化的是jQuery.fn.init函数
jQuery = function( selector, context ){
return new jQuery.fn.init( selector, context );
}
那么问题来了,这个new出来的对象如何访问jQuery原型上的方法呢,关键在于这段代码
init = jQuery.fn.init = function(){}
init.prototype = jQuery.fn;
通过原型链的方式,将jQuery.fn全部挂载到了init的原型链中。(有关原型继承可参看原型继承) jQuery可调用的方法分为两种,一种是jQuery本身可调用的方法,即使用jQuery.extend扩展的;另外一种是生成的jQuery对象可以使用的方法,即使用jQuery.fn.extend扩展的。
扩展开发
jQuery对开发者提供了jQuery.fn.extend方法进行jQuery对象扩展。
jQuery.extend = jQuery.fn.extend = function(){
var i = 1, length = arguments.length;
if( i === length ){
target = this;
i--;
}
}
通过target=this使得同一个函数实现了分别对jQuery自身和jQuery.fn的扩展
extend用法
extend( true, obj1, obj2, ... )//深层拷贝 extend( obj1, obj2 )//浅层拷贝 extend( obj )//自身对象的扩展 具体代码分析如下:
jQuery.extend = jQuery.fn.extend = function(){
var options,//拷贝的对象
name,//拷贝对象中的键名
src,//被修改对象中的值
copy,//拷贝对象的值
copyIsArray,//是否是一个数组
clone,//深层拷贝中被修改的对象
target = arguments[0] || {},//被修改的对象
i = 1,//默认开始遍历的起始索引值
length = arguments.length,//参数长度
deep = false;//默认浅层拷贝
//处理深层拷贝的情况
if( typeof target === "boolean" ){
deep = target;
target = arguments[i] || {};
i++;
}
//处理被修改对象为字符串或其他非对象、函数类型的情况,初始化为空对象
if( typeof target !== "object" && !jQuery.isFunction(target) ){
target = {};
}
//扩展jQuery自身
if( i === length ){
target = this;
i--;
}
for( ; i < length; i++ ){
if( ( options = arguments[i] ) != null ){
for( name in options ){
src = target[ name ];
copy = options[ name ];
//防止死循环
if( target === copy ){
continue;
}
//深层拷贝,拷贝的值非空,纯对象或者数组
if( deep && copy && ( jQuery.isPlainObject(copy) || ( copyIsArray = jQuery.isArray( copy ) ) ) ){
//数组
if( copyIsArray ){
copyIsArray = false;
clone = src && jQuery.isArray( src ) ? src : [];
}else{
//对象
clone = src && jQuery.isPlainObject( src ) ? src : {};
}
target[ name ] = jQuery.extend( deep, clone, copy );
}else if( copy !== undefined ){
target[ name ] = copy;
}
}
}
}
return target;
}