深入理解jquery中extend的实现

2020-05-27 17:58:03易采站长站整理

如我们使用

getOpt(_default, obj1, obj2, obj3);
得到的_default值是
{name: “obj2”, age: “67”, sex: {error: “sorry, I dont't kown”}}
,可是若:


_default.sex.error = 'hello world';

那么

obj3.sex.error
也会跟着修改,因为obj3.sex是一个object类型。

不过$.extend()也提供了深度拷贝的方法:

jQuery.extend( [deep ], target, object1 [, objectN ] )
。若第一个参数是boolean类型,且值是true,那么就会把第二个参数作为目标参数进行合并。


var obj = {name:'wenzi', score:80};
var obj1 = {score:{english:80, math:90}}
$.extend(true, obj, obj1);
obj.score.english = 10;
console.log(obj.score.english); // 10
console.log(obj1.score.english); // 80

执行后我们发现,无论怎么修改obj.score里的值,都不会影响到obj1.score了。

2. jQuery中extend实现原理

其实不看源码,对extend大致的过程应该也是了解的:对后一个参数进行循环,然后把后面参数上所有的字段都给了第一个字段,若第一个参数里有相同的字段,则进行覆盖操作,否则就添加一个新的字段。

下面是jQuery中关于extend的源码,我就在源码上进行注释讲解了,随后再在后面进行总结:


// 为与源码的下标对应上,我们把第一个参数称为`第0个参数`,依次类推
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {}, // 默认第0个参数为目标参数
i = 1, // i表示从第几个参数凯斯想目标参数进行合并,默认从第1个参数开始向第0个参数进行合并
length = arguments.length,
deep = false; // 默认为浅度拷贝

// 判断第0个参数的类型,若第0个参数是boolean类型,则获取其为true还是false
// 同时将第1个参数作为目标参数,i从当前目标参数的下一个
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;

// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}

// 判断目标参数的类型,若目标参数既不是object类型,也不是function类型,则为目标参数重新赋值
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}

// 若目标参数后面没有参数了,如$.extend({_name:'wenzi'}), $.extend(true, {_name:'wenzi'})
// 则目标参数即为jQuery本身,而target表示的参数不再为目标参数