Need to understand Javascript object references
我正在从JohnResig的网站上查看这段代码。我不明白的是,当忍者对象设置为空对象时,Yell方法仍然对武士可用。
是因为在忍者身边仍然有一个参考资料,它不是垃圾收集的吗?
1 2 3 4 5 6 7 8 9 10 11 12 | var ninja = { yell: function(n){ return n > 0 ? yell(n-1) +"a" :"hiy"; } }; var samurai = { yell: ninja.yell }; ninja = {}; console.log(samurai.yell(2)); //hiy |
http://ejohn.org/apps/learn/14(原始源代码,我稍微修改了一下以删除命名函数表达式)。
在以下代码中:
1 2 3 4 5 | var ninja = { yell: function(n){ return n > 0 ? yell(n-1) +"a" :"hiy"; } }; |
ninja.yell的值是对函数的引用。作业:
1 | var samurai = { yell: ninja.yell }; |
为samurai.yell指定一个值,该值是对同一个函数的引用(即ninja.yell引用的函数)。然后:
1 | ninja = {}; |
为忍者分配一个新的空对象值。它对指定给samurai.yell的值没有影响,该值仍引用函数。
变量有值,值有类型。有一个称为引用类型的特殊类型,"…用于解释诸如delete、type of和赋值运算符等运算符的行为"。因此,当一个对象在赋值表达式中时,赋值是类型引用。
因此变量仍然有一个值,但它的值是一个引用。
断开"忍者"的"Yell"属性引用的匿名函数:
1 2 3 4 5 6 7 | function yell(n) { return n > 0 ? yell(n-1) +"a" :"hiy"; } var ninja = { yell: yell }; |
现在,在重新分配"忍者"时,更容易看到函数"yell"不会被"deleted"。
当你这样做的时候:
1 | var samurai = { yell: ninja.yell }; |
你把任何忍者的参考(即
以javascript解释器将要执行的方式运行执行:
此时,"堆"看起来如下:
1 2 3 | func1 = n => return n > 0 ? yell(n-1) +"a" :"hiy" obj1 = { yell: func1 } ninja = obj1 |
此时,"堆"看起来如下:
1 2 3 4 5 6 | func1 = n => return n > 0 ? yell(n-1) +"a" :"hiy" obj1 = { yell: func1 } // this no-longer has any references and will be GC'd at some point obj2 = { yell: func1 } obj3 = {} samurai = obj2 ninja = obj3 |
重要的是要查看此源的原始未修改源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1. | var ninja = { 2. | yell: function(n){ 3. | return n > 0 ? ninja.yell(n-1) +"a" :"hiy"; 4. | } 5. | }; 6. | assert( ninja.yell(4) =="hiyaaaa","A single object isn't too bad, either." ); 7. | 8. | var samurai = { yell: ninja.yell }; 9. | var ninja = null; 10. | 11. | try { 12. | samurai.yell(4); 13. | } catch(e){ 14. | assert( false,"Uh, this isn't good! Where'd ninja.yell go?" ); 15. | } |
将
What I don't understand is when the ninja object is set to an empty object, the yell method is still available to samurai.
理解JavaScript中的赋值方式很重要。Javascript有很多方便的速记符号,当你刚接触到该语言时,这些符号会让你很难理解。
1 | var samurai = { yell: ninja.yell }; |
是说:
1 2 3 | var samurai; samurai = new Object(); samurai.yell = ninja.yell; |
调用
在JavaScript中,函数也是对象。它们是通过引用传递的。
在示例的第9行,
举个例子更容易看到:
1 2 3 4 5 6 7 8 9 | var foo, bar; foo = { fizz: 'buzz' }; bar = foo; foo = null; console.log(bar.fizz); //buzz |
Is it because since there is still a reference lying around to ninja, it wasn't garbage collected?
在执行示例脚本的第9行之后,不再有任何对已位于