2016-05-26 1 views
2

Основываясь на своем опыте и информации в 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:

Примечание: сокращенная синтаксис использует указанную функцию вместо анонимных функций (как в ... обув: функция() {} ...). Именованные функции можно вызывать из тела функции (это невозможно для анонимной функции, так как для ссылки нет идентификатора). Для получения дополнительной информации см. Функцию.

Но по моему варианту это противоречит наблюдению, поскольку он говорит, что такая функция является именованной функцией, и поэтому она должна быть доступна из тела функции.

Функция имеет имя, потому что obj.foo.name является foo, но foo недоступен изнутри.

Является ли наблюдаемое поведение правильным в отношении спецификаций, и где это определено в спецификациях?

ответ

3

Функция имеет имя, потому что obj.foo.name является foo, но foo не доступен из внутри себя.

Да. Это новый тип функции, введенный с ES6: анонимная функция . Э-э.

Свойство функции ES6 получено не больше от токена между ключевым словом function и открывающей скобкой, но также от имени переменной или свойства, которому оно было присвоено. Краткое определение методом

var obj = { 
    foo() { … } 
} 

семантически эквивалентен

var obj = { 
    foo: function() { … } 
} 

в ES6 - как создать функцию с .name из "foo" (ср §14.3.9 и §12.2.6.9.).

Эта функция, однако, не является названным функциональным выражением, который создает константу foo в области промежуточного закрытия, что позволяет ей ссылаться на себя.

Если вы хотите использовать самооценку в определении функции, вы должны использовать .

ли наблюдаемое поведение правильным в отношении спецификации

Да. Кажется, что MDN здесь неисправен.

... и где это определено в спецификации?

В целом в целом Chapter 14: Functions and Classes.

В частности, поведение выраженного имени функции указано в §14.1.20 с акцентом на funcEnv, который не может быть найден при оценке анонимных выражений функции.

Свойство .name создано в abstract SetFunctionName method, которое вызывается со всей спецификации (выполните поиск). Особенно интересные случаи идут вместе с вызовом IsAnonymousFunction­Definition, который проверяет, не содержит ли выражение токен именования.

1: Я только что сделал этот термин. В случае, если вы не заметили :-)

+0

Благодарим вас за отзыв. Я подробно рассмотрю главу 14. Его меньше о том, что я хочу самостоятельно ссылаться на себя, но больше об этом пишу модуль для esformatter для рефакторинга кода, поэтому я хочу быть уверенным в этом. –

+1

Мне нужно привыкнуть, что 'foo: function() {...}' приведет к тому, что 'foo.name' будет' foo', но, похоже, является логическим шагом для обеспечения согласованности всех представлений. –

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

Если вы transpile это с помощью Babel

let x = {foo() {}}; 

Вы получите

var x = {foo: function foo() {}}; 

Так это выглядит, как если бы вы tranpsile код, его будет работать должным образом, потому что Бабель даст имена функциям.

+0

Благодарим вас за обратную связь, поэтому '{foo() {}}' не является именованной функцией, как указано в MDN? Я работаю над расширением esformatter для рефакторинга кода, поэтому я действительно хотел бы знать, как он определен в ES6. –

+0

@ t.niese Я только что быстро проверил в babel, и он переводит '{foo() {}}' с именем функции. Все еще не уверен, что спецификация tho, извините: \ – naomik

+0

Я также сделал тест на babel перед публикацией :). Если вы напишете 'let x = {foo() {console.log (typeof foo)}};' результат немного усложняется. –

Смежные вопросы