首先呢我有一个数组,存放了多个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() 为啥要这样实现,是从性能的角度考虑,还是方便调用?(方便个鬼啊,很容易就踩坑了)