匿名函数名称在浏览器之间的行为不同?

Anonymous function name behaves differently between browsers?

我正在做一些书中的练习,我遇到了这个例子:

<html>
  <body>
      <script type="text/javascript">
        var canFly = function() { return true;}
        
        window.onload = function() {
          console.log('Assert: "' + window.canFly.name+'"');
        }
      </script>
  </body>
</html>

但是在 Chrome 51 和 Firefox 46.0.1 中执行时,我发现它们的行为有点不同。

也就是说,Chrome 似乎是 return Assert: "canFly",而 Firefox return 是 Assert: ""。根据这本书,Firefox 的行为是预期的。

我的问题是这两种行为中的任何一种 'correct' 参考规范?

我认为这是你的答案:Function "name" property (ES6)

基本上,它是 Chrome 的 DevTools 的“智慧”,而且显然是新的 JS 标准支持的行为。

  • ES5 规范没有提及函数的 .name 属性,因此它应该是 undefined.

  • (部分)浏览器仍将函数名作为一项功能实现,匿名函数将没有名称,因此应该是""。此外,开发人员工具会更聪明,并命名一些匿名函数用于调试目的(但不给它们一个 .name 属性)。

  • ES6规范给出了赋值给变量a.name属性的匿名函数表达式,所以应该是"canFly".

现在选择你自己考虑的那些 "correct" :-) 你的书可能有点过时,FF 在实现这个新的 ES6 功能方面有点落后。

当您阅读一本关于不断变化的网络技术的书时,预计其中的部分或全部信息会过时。

在 ES5 中没有为 function instances, nor was it defined for Function.prototype 定义 name 属性。


在 ES2015 中,name 属性 被定义为 function instances:

The value of the name property is an String that is descriptive of the function. The name has no semantic significance but is typically a variable or property name that is used to refer to the function at its point of definition in ECMAScript code. This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

Anonymous functions objects that do not have a contextual name associated with them by this specification do not have a name own property but inherit the name property of %FunctionPrototype%.

它也被定义为 function.prototype:

The value of the name property of the Function prototype object is the empty String.

还有一个算法定义为 SetFunctionName,它似乎可以处理在各种情况下分配 name 属性,例如当函数用作对象字面量。


这是我挖的最深的兔子洞。如果 Chrome 和 Firefox 对 SetFunctionName 有不同级别的支持,或者如果 ES2015 和 ES2017 规范之间存在差异会导致您看到的行为,我不会感到惊讶。

Variables and methods can infer the name of an anonymous function from its syntactic position (new in ECMAScript 2015).

var f = function() {};
var object = {
  someMethod: function() {}
};

console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"

阅读有关 inferred function names 的内容可能会有帮助。