关于jquery.extend()的坑:我的数组变成相同元素了?

首先呢我有一个数组,存放了多个json对象。这些json对象的属性有缺失,我设置了一个对象模板来存放默认值

先来看一段代码

var source = [
    {
        name: 'dapianzi',
        born: '2013',
        more: {
             128,
        }
    },
    {
        sex: 'female',
        more: {
            weight: 48,
            height: 168,
        }
    },
    {
        name: 'any'
    }
];
var default = {
    name: 'nobody',
    born: '1990',
    sex: 'man',
    more: {
         666,
        height: 888,
         777,
    }
};
// for (var i in source)
// for (var i=0; i<source.length; i++)
// source.forEach()
source = source.map(function(item, key){return $.extend(true, default, item);});
console.log(source);

运行结果

???
为什么数组元素全部变成一样的了???

关于javascript 中的对象赋值

var a = {x: 1, y: 2};
var b = a;
b.z = 3;
console.log(b); // {x:1, y:2, z:3}
console.log(a); // {x:1, y:2, z:3}

可以看出对一个变量赋值其他的对象变量,是直接赋值引用的(道理我都懂,为什么数组元素变成一样的了??)

jQuery.extend() 的实现

之前使用 $.extend() 的场景比较单一,都是单一默认配置项的继承。
这次的场景不一样的地方在于,在一个循环体里面,默认的配置项需要使用多次,并且使用了变量存储。

关键的地方来了,查阅jQuery文档发现了这么一段话

是说传入的第一个非布尔参数(布尔true表示深度拷贝继承)是会被改变的!
也就是说,上面的代码实际上类似于这样:

var source = [{x:1},{x:2},{x:3},];
var opt = {y: 0};
for (var i in source) {
    var tmp = opt;
    // opt extend source item.
    tmp.x = source[i].x; // 等价于 opt.x = source[i].x
    source[i] = tmp; // 等价于 source[i] = opt
}

执行之后 source 里面的元素是什么情况呢?

[opt, opt, opt]

因此我们会看到数组元素全部变成相同的了。

反思总结

  • 对别人造的轮子不熟悉,想当然地认为是自己想象中的实现
    我想当然的认为它的实现方式
function(a, b){
    var tmp = {}
    for (var i in a) {
        tmp[i] = a[i]
    }
    for (var j in b) {
        tmp[j] = b[j]
    }
    return tmp;
}
  • 奇怪 jQuery.extend() 为啥要这样实现,是从性能的角度考虑,还是方便调用?(方便个鬼啊,很容易就踩坑了)
原文地址:https://www.cnblogs.com/dapianzi/p/8926709.html