我可以通过这个简单的代码片段来解释这个问题:
var child1 = {name: 'child1'};
var child2 = {name: 'child2'};
var parent = {
_cache: [], // storage var
writeCache: function(key, val)
{
console.log('writing cache::'+this.name);
this._cache[key] = val;
},
readCache: function(key)
{
if(this._cache[key] == undefined)
{
return false;
}
return this._cache[key];
},
};
jQuery.extend(child1, parent);
jQuery.extend(child2, parent);
child1.writeCache('myKey', 123);
console.log(child1.readCache('myKey')); // returns 123 as expected
console.log(child2.readCache('myKey')); // returns 123 unexpectedly (for me at least)
见最后一行:
console.log(child2.readCache('myKey'));
现在为什么当我们只访问child1的writeCache()?
时它会返回123答案 0 :(得分:4)
jQuery的extend方法复制第二个对象中的所有内容并将其放在第一个对象中。
包括将引用复制到您分配给parent._cache
的数组。因此,无论何时从任何对象缓存中读取或写入,都可以访问同一个数据存储。
要避免这种情况,请进行深层复制。
jQuery.extend(true, child1, parent);
jQuery.extend(true, child2, parent);
顺便说一句,由于您正在处理命名键,因此请使用Object,而不是Array。
_cache: {}, // storage var
答案 1 :(得分:1)
_cache
中的parent
被复制到两个子对象。基本上,会发生以下情况:
child1._cache = parent._cache
child2._cache = parent._cache
但现在他们都在内存中引用相同的数组(js传递相同的引用)。因此,当你改变它时,你应该期望它反映在别处。例如:
parent = {_cache:[]}
child1 = {}
child2 = {}
child1._cache = parent._cache
child2._cache = parent._cache
child1._cache.push(9)
child2._cache; // [9]
您可以使用原型继承解决此问题:
function parent(){
this._cache = [];
}
parent.prototype.writeCache = ...
parent.prototype.readCache = ...
child1 = new parent();
child2 = new parent();
child1.writeCache('myKey', 123);
console.log(child1.readCache('myKey')); // 123
console.log(child2.readCache('myKey')); // undefined (/false in your case)
您还可以将Object.create
与原始代码一起使用:
child1 = Object.create(parent, {_cache: { value:[] }} )
child2 = Object.create(parent, {_cache: { value:[] }} )
答案 2 :(得分:1)
jQuery.extend
与继承无关。它将第二个对象的属性合并到第一个对象。这意味着您_cache
的引用位于child1
和child2
。
答案 3 :(得分:1)
您得到了结果,因为_cache
- parent
成员在您的示例中通过引用复制。如果您查看jQuery的API-docs,可以通过将true
作为第一个参数传递给jQuery.extend
来强制执行深层复制。
在此处查看有效的jsFiddle:http://jsfiddle.net/mLfUE/
答案 4 :(得分:0)
这大约是jQuery's extend method,而不是内置于Javascript中的内容。
在这种情况下,您使用.extend()来扩展带有父对象属性的child2对象。
.extend()的jQuery文档在某一点上提到:
默认情况下,$ .extend()执行的合并不是递归的;
这表明父元素的属性被整体复制到child2中。在Javascript中,对象(以及因此也是数组)通过引用复制。 _cache是一个数组,所以当jQuery的extend方法是将对象从parent复制到child2时,它会复制对现有_cache Array的引用,而不是复制其所有值,因此它最终会引用与父对象相同的数组。对同一数组的引用也被复制到前一行中的child1中。
通过引用复制时,引用继续指向同一个对象,并使用其任何一个引用修改该对象将影响原始对象。