根据我的经验以及Why use named function expressions?和kangax.github.io: Named function expressions中的信息,很清楚为什么以下两个示例会产生给定的输出:
示例1:
var f = function foo() {
console.log(foo);
}
console.log( typeof foo === "undefined" ); // true
console.log( typeof f !== "undefined" ); // true
console.log( f.name ); // foo
示例2:
var obj = {
fooA: function foo() {
console.log('fooA -> ' + foo.toString());
},
fooB: function foo() {
console.log('fooB -> ' + foo.toString());
}
}
obj.fooA(); // the source of fooA
obj.fooB(); // the source of fooB
console.log(typeof foo === "undefined"); // true
但是我试着弄清楚为什么标识符不适用于以下示例中的封闭范围:
var obj = {
foo() {
console.log(typeof foo === "undefined"); // true
}
}
obj.foo();
console.log(obj.foo.name); // foo
我猜它是在某处定义的,但有关此的信息似乎分布在整个specs上。我发现的唯一明确的陈述是MDN: Method definitions:
注意:简写语法使用命名函数而不是匿名函数(如... foo:function(){} ...)。可以从函数体中调用命名函数(这对于匿名函数是不可能的,因为没有要引用的标识符)。有关更多详细信息,请参阅函数。
但是在我的选择中,这与观察结果相矛盾,因为它说这种函数是一个命名函数,因此它应该可以从函数体中访问。
该函数有一个名称,因为obj.foo.name
为foo
,但foo
无法从内部访问。
关于规格,观察到的行为是否正确,这在规范中定义了什么?
答案 0 :(得分:3)
该函数有一个名称,因为
obj.foo.name
为foo
,但foo
无法从内部访问。
是。这是ES6引入的一种新类型的函数:命名的匿名函数 1 。呃。
ES6函数的name
属性不再来自function
关键字和左括号之间的标记,而是来自它分配给它的变量或属性名称。简洁的方法定义
var obj = {
foo() { … }
}
在语义上等同于
var obj = {
foo: function() { … }
}
ES6中的 - 都创建了一个.name
"foo"
{cp。§14.3.9和§12.2.6.9)的函数。
此函数不是命名函数表达式,它在中间闭包范围内创建foo
常量,允许它引用自身。
如果您想在函数定义中使用自引用,则可以使用this.foo
。
关于规格的观察行为是否正确
是。 MDN似乎再次出现问题。
......这在规格中定义了什么?
基本上在整个Chapter 14: Functions and Classes。
特别是,命名函数表达式行为在§14.1.20中指定,重点是在评估匿名函数表达式时找不到的funcEnv
。
.name
属性是在abstract SetFunctionName
method中创建的,该属性是从整个规范中调用的(搜索它)。特别有趣的案例与IsAnonymousFunctionDefinition
调用一起检查表达式是否包含命名令牌。
1:我刚刚提出这个词。如果您没有注意到: - )
答案 1 :(得分:1)
简答:
您需要使用this.foo
({
foo(x) {
return x > 3 ? x : this.foo(x+1);
}
}).foo(1); // => 4
与你有这个没什么不同:
({
foo: function(x) {
return x > 3 ? x : this.foo(x+1);
}
}).foo(1); // => 4
可以从函数体
调用命名函数
是的,所以如果命名为,那么你可以在没有this
的情况下使用它:
({
foo: function foo(x) {
return x > 3 ? x : foo(x+1);
}
}).foo(1); // => 4
关于规格,观察到的行为是否正确,这在规范中定义了什么?
这部分我无法回答你,抱歉。
<强> babel.js 强>
如果你使用babel来解释这个
let x = {foo() {}};
你会得到
var x = {foo: function foo() {}};
所以看起来如果你传递你的代码,它会正常工作,因为Babel会给这些函数命名。