javascript - 引用匿名函数与命名函数的属性

标签 javascript

阅读 John Resig 的 Learning Advanced Javascript , 我遇到了两张我不完全理解的幻灯片。

幻灯片 #13 - 引用作为匿名函数的属性。第二个断言失败。

var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); // PASS

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
  samurai.yell(4); 
} catch(e){ 
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); // FAIL
}

幻灯片 #14 - 引用作为已定义函数的属性。第二个断言通过。

var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); // PASS

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." ); // PASS

此处唯一的区别是 yell 是幻灯片 14 中的命名函数。为什么即使在设置原始对象后,对定义为命名函数的属性的引用仍然存在 (ninja) 到一个新对象(甚至是 null)?

最佳答案

The only difference here is that yell is a named function in slide 14.

不,这不是唯一的区别,也不是最重要的区别(尽管它与重要的区别有关)。

在第一个中,注意 ninja.yell 是如何定义的:

var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^^^^^^^
  } 
}; 

它在自身内部明确使用了 ninja.yell。因此调用它会查找变量 ninja,然后尝试查找 yell 作为 ninja 的属性。

将其与第二个示例中的定义进行比较:

var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^
  } 
};

yell 不再使用变量 ninja,它仅使用自身的范围内标识符(通过命名函数表达式为函数命名而创建的标识符).

这就是为什么在第一个例子中 ninja 被清空的原因:

var ninja = null; 

...第一个开始失败;你不能在 null 上查找 yell

但是当 ninaj 在第二个中被替换时(我不明白为什么 John 在这两种情况下都没有使用 null,但无论如何):

var ninja = {};

...yell 不在乎,因为它不使用ninja


旁注:从 ES2015 开始,yell 的两个版本都不是匿名函数,即使第一个版本是使用匿名函数表达式创建的。在 ES2015 中,函数可以根据上下文获取其名称,其中一种获取名称的方法是在对象初始值设定项中分配给对象属性。不过,这对解决这个问题没有帮助,因为名称不是函数内的范围内标识符,就像您使用命名函数表达式时那样。

关于javascript - 引用匿名函数与命名函数的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42766177/

相关文章:

javascript - 带有 javascript 的选项卡在 IE 中不起作用

javascript - 使用更改文本自动调整定义的 DIV 中的字体大小

javascript - 无论输入类型 ="number"的验证如何,都保留输入值

javascript - 如何使用 Underscore.js 对数组的数组执行并集或交集

javascript - AngularJS 未在 Controller 中接收广播

javascript - 展开/折叠引导 Vue.js 表中的所有操作

javascript - 隐藏表头列边框

javascript - Angular 动画: Slider Effect

javascript - 以编程方式设置 Angular 4 复选框

javascript - XRegExp 通过工作 unicode 检查返回 false\p?