kev*_*guy 5 javascript javascript-objects
我正在阅读JavaScript Ninja的秘密,并遇到了一个编码示例:
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
var samurai = { yell: ninja.yell };
//var ninja = {};
//delete ninja;
samurai.yell(4);
Run Code Online (Sandbox Code Playgroud)
如果我取消注释第二个注释行,samurai.yell(4)运行正常,我理解它samurai仍然有它的引用最初引用的函数ninja.yell,delete删除.
但是,如果我改为运行第一个注释行,samurai.yell(4)则会出错.
有人可以解释引擎盖下发生了什么吗?
我想如果你指定ninja为be undefined,将创建一个新的引用并链接到ninja,原始引用仍然存在,并且由于samurai仍然有对该函数的引用,因此垃圾收集不会出现并在内存中将其删除.
我查看了@mrid 和@Amadan 的答案并思考了一下,我想我已经弄清楚并提出了一个更简单的答案,而我在问题中的解释并不完全正确。
如果我取消注释第一行注释,
var ninja = {};
Run Code Online (Sandbox Code Playgroud)
我将 ninja 分配给一个空对象,因此,我尝试运行“samurai.yell(4);”,但出现错误。原因是因为武士试图通过其“范围链”(即一些闭包魔法,它确实找到了忍者,但是当它试图查找忍者是否有属性大喊时,它消失了,因此出现错误。尽管武士仍然持有对该匿名函数的引用(这意味着它仍然可以运行该函数),当该匿名函数尝试运行时ninja.yell(),它再也找不到它,因此出现错误。
解决这个问题的方法当然是使用this,
var ninja = {
yell: function (n) {
return n > 0 ? this.yell(n-1) + "a" : "hiy";
}
};
var samurai = { yell: ninja.yell };
var ninja = {};
samurai.yell(4);
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用命名函数表达式,
var ninja = {
yell: function foo(n) {
return n > 0 ? foo(n-1) + "a" : "hiy";
}
};
var samurai = { yell: ninja.yell };
var ninja = {};
samurai.yell(4);
Run Code Online (Sandbox Code Playgroud)
一切都应该正常。
如果我取消注释第二行注释,
delete ninja;
Run Code Online (Sandbox Code Playgroud)
我其实什么也没做。delete仅用于“删除”对象的属性(您永远无法删除 Javascript 中的任何内容,垃圾收集会处理该操作),如果操作成功则返回 true,否则返回 false。因此,“删除”对ninja不起作用,所以简单来说,当我取消注释“delete ninja;”时,我没有对ninja做任何额外的事情,一切仍然正常工作。
因此,您可以忘记我在问题中所说的有关“引用”和“删除”的所有内容,它们不相关且不真实。