缩写语法方法定义的标识符范围

时间:2016-05-26 12:57:11

标签: javascript ecmascript-6

根据我的经验以及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.namefoo,但foo无法从内部访问。

关于规格,观察到的行为是否正确,这在规范中定义了什么?

2 个答案:

答案 0 :(得分:3)

  

该函数有一个名称,因为obj.foo.namefoo,但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中创建的,该属性是从整个规范中调用的(搜索它)。特别有趣的案例与IsAnonymousFunction­Definition调用一起检查表达式是否包含命名令牌。

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会给这些函数命名。

相关问题