2013-03-29 75 views
1

我在看Backbone的v1.0.0源代码,并注意到一些有趣的事情。在Backbone.Events对象“”方法似乎是可变到对象值:将JavaScript变量链接到对象值。

on: function(name, callback, context) { 
    if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; 
    this._events || (this._events = {}); 
    var events = this._events[name] || (this._events[name] = []); 
    events.push({callback: callback, context: context, ctx: context || this}); 
    return this; 
}, 

的“事件”变量被设置为“this._events [名称]“值,它既可以是现有数组,也可以设置为空数组。奇怪的部分是将对象推入该数组的下一行。推后,如果你现在检查“this._events [name]”的值,它现在在它的数组末尾有这个新对象。对我来说,看起来这两个实质上是连接;当你更新一个时,另一个也会更新。

我以前没有遇到类似这样的事情,并且执行简单的浏览器控制台测试来确认此行为。你更新一个,另一个也得到更新。它似乎只能用于数组的对象值。任何人都可以解释这里发生了什么?我有点困惑?

回答

3

var events = this._events[name] || (this._events[name] = []);行之后,同时events变量和this._events[name]指向相同阵列。由于它们都指向相同的数组,因此无论您使用events.push(...)还是this._events[name].push(...),它都会推送所指向的一个数组上的元素。

这是完全一样的:

var a = [];   // Create an empty array, reference it from `a` 
var b = a;    // Now, `b` and `a` both point to the same array 
a.push("foo");   // Put an entry in the array 
console.log(a.length); // "1", unsurprisingly 
console.log(b.length); // "1", because both `a` and `b` point to the same array 
0

实际上发生的事情是一个简单的方法,如果它不存在于事件初始化数组。 Events是一个指向this._events[name]的指针,它本身就是一个指向数组的指针。如果数组不存在,则它被初始化为一个新的数组。

试试这个:

var x = false || 2; 
console.log(x); 
x = 1 || 2; 
console.log(x); 
1

您更新一个,而另一个得到更新过。

您只有一个数组,它正在更新。

将变量看作“指针”,当它们将一个对象作为一个值(是一个数组计算为一个对象)时。该变量不是对象,它只是保存对该对象的引用。

这可以通过该片段更简单地证明:

您这儿只有一个阵列,并且两个ab变量指向同一个数组。您可以修改该数组,并且可以从指向该数组的任何变量中获取这些修改。