前置知识
- arguments
- 重载
- 深拷贝/浅拷贝
代码概况
上一节我们打开了/src/core.js文件,但是仅仅看了它的jQuery对象的赋值。这节我们来仔细分析core.js文件中的一个重要内容——extend。
如果,简单翻阅过jquery源码的话,你会发现源码中,也有多处调用了extend函数。所以,这个Extend不光为外部提供调用,jquery内部同样使用,可以说是一个基础函数。重要性可见一斑。
首先,通过jQuery.extend = jQuery.fn.extend,我们得知,jQuery.extend和的代码实现是相同的。关键在于方法的重载(jquery中使用了大量的重载)。
功能说明
在阅读源码之前,我们先翻阅api手册了解其主要的几种功能用法,主要有如下几种:
jQuery.extend( target [, object1 ] [, objectN ] )
合并object1, objectN到target对象jQuery.extend( [deep ], target, object1 [, objectN ] )
深度复制合并对象,第一个参数是boolean类型的true时,将object1, objectN深度复制后合并到targetjQuery.extend(object)
合并object对象到jQuery对象中jQuery.fn.extend(object)
合并object对象到jQuery.prototype(也就是jQuery.fn)对象中
这里解释下3和4的区别。一种是对jquery实例对象进行扩展,一种是对原型对象进行扩展。如果明白js原型链的话就很容易理解,后者的扩展会在所有jquery对象中体现,而前者不会。
源码分析
接下来,看一下源码:
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 = {};
}
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;
};
第一步:target被赋值成第一个参数,并判断是不是boolean值,如果是,deep赋值为第一个参数,target赋值为第二个参数;
第二步:接着判断target,是不是一个字符串,或者其他,是的话target就被赋值为空对象,主要用于容错;
第三步:判断剩余参数长度(除去deep)是不是等于1,是的话,target就被赋值为this。如果是jQuery.extend调用,this就是jQuery,如果是jQuery.fn.extend,this就是jQuery.fn;
第四步:把i(用于标记第一个object的index)后面的对象参数扩展进target即可,其中注意判断深/浅拷贝就行。
至于如何扩展,逻辑很简单,简单实现如下:
function(target, options) {
for (name in options) {
target[name] = options[name];
}
return target;
}
这里就不累述了。