Начиная с ES2015 (ES6), функции имеют собственные имена (включая официальное свойство name
), и имена присваиваются при создании функции различными способами в дополнение к очевидному объявлению функции и именованному выражению функции, например, присвоение переменным (имя функции устанавливается равным имени переменной), присвоение свойствам объекта (имя функции устанавливается равным имени свойства), даже значения по умолчанию для параметров функции (имя функции устанавливается равным имени параметра). Но присвоение свойству существующего объекта (например, не в инициализаторе объекта) не присваивает функции имя этого свойства. Почему нет? Конечно, должна быть конкретная причина, по которой это нежелательно / невозможно. Что это было?
Чтобы было ясно: я не спрашиваю, как это обойти. Я спрашиваю, что мешает разрешить этот, казалось бы, очевидный случай, когда так много других (включая значения параметров по умолчанию!). Должна быть веская причина.
Пожалуйста, не рассуждайте и не теоретизируйте. У TC39 была причина не включать его. Мне интересно, в чем была причина. Я просмотрел заметки о совещании TC39, но еще не нашел их. Ближайшее, что я нашел до сих пор, - это Аллен Вирфс-Брок, отвечая Берги, чтобы сказать консенсуса по поводу этой формы не было из-за «различных возражений», но, к сожалению, он не сказал, в чем заключаются эти возражения.
Подробности:
Все перечисленное ниже присваивает имя foo
функции в совместимом браузере:
// Requires a compliant browser
// Assigning to a variable or constant...
// ...whether in the initializer...
{
let foo = function() { };
console.log("1:", foo.name); // "foo"
}
{
const foo = function() { };
console.log("2:", foo.name); // "foo"
}
// ...or later...
{
let foo;
foo = function() { };
console.log("3:", foo.name); // "foo"
}
// As an initializer for an object property
{
const obj = {
foo: function() { }
};
console.log("4:", obj.foo.name); // "foo"
}
// Or as a method
{
const obj = {
foo() { }
};
console.log("5:", obj.foo.name); // "foo"
}
// Even if it's a computed property name
{
let name = "f";
const obj = {
[name + "o" + "o"]() { }
};
console.log("6:", obj.foo.name); // "foo"
}
// As a default value for a parameter
(function(foo = function() { }) {
console.log("7:", foo.name); // "foo"
})();
// ...and a bunch of others
Но присвоение свойству существующего объекта вне инициализатора объекта не приводит:
const obj = {};
obj.foo = function() { };
console.log("Nope:", obj.foo.name);
Насколько я могу судить, это покрывается этот раздел спецификации, который явно устанавливает имя функции только в том случае, если IsIdentifierRef из LeftHandSideExpression истинно (что, очевидно, не для ссылок на свойства).
Итак, повторяя сверху: почему бы и нет? Конечно, должна быть конкретная причина, по которой это нежелательно / невозможно. Что это было?
foo["2for1"] = function...
полностью действителен, но 2for1 не является допустимым именем функции ... хотя это в равной степени применимо к вычисленному примеру. - person Jared Smith   schedule 12.12.20162for1
- допустимое имя функции: jsfiddle.net/Lx825mgf Function имена, как и имена свойств, не обязательно должны быть действительными идентификаторами. :-) (Изменить: Хех, только что видел, как отредактировали ваш комментарий.) - person T.J. Crowder   schedule 12.12.2016foo.2for1 = function...
иfunction 2for1() {}
оба выбрасывают, потому что идентификаторы JS не могут начинаться с чисел. - person Jared Smith   schedule 12.12.2016MemberExpression[Expression] = FunctionExpression
. - person Jared Smith   schedule 12.12.2016obj.prop1 = obj.prop2 = function() {}
? Ничего не назначать - очень удобный способ избежать подобных спорных вопросов. - person artem   schedule 13.12.2016prop2
. Идентично поведениюvar x = y = function();
. имя функции ==y
. Никакой двусмысленности нет, имя функции присваивается при создании функции. Фактически, то, чтоobj.prop1 = obj.prop2
не работает, аvar x = y
работает, само по себе сбивает с толку. - person CodingIntrigue   schedule 13.12.2016var x = y = function() ...
, первое имя, которое я вижу, этоvar x
, поэтому тот факт, что функция называетсяy
, возможно, сбивает с толку и может считаться ошибкой. Я думаю, что правильный способ присвоить имя при создании функции - использовать однозначный синтаксис именованной функции:var x = y = function y() {}
- person artem   schedule 13.12.2016x = y = function() { };
оценивается какy = function() { }
(создание функции, которая дает ей ее имя, присвоениеy
), затем это результирующее значение (существующая ссылка на функцию) присваиваетсяx
. Выполнение чего-либо другого нарушило бы семантику стандартных выражений и потребовало бы чрезвычайно сложных механизмов в спецификации для достижения. - person T.J. Crowder   schedule 13.12.2016a = b
присваивает значениеb
a
, обычноb
не зависит отa
каким-либо образом. Создание особого случая, когдаb
является функцией, производной отa
, кажется произвольным и ненужным, учитывая, что в течение долгого времени существовал способ дать имя любой функции. - person artem   schedule 13.12.2016const obj = {}; Object.defineProperty(obj, 'foo', {value:function(){}}); obj.foo.name;
возвращает _2 _... что согласованно, но, вероятно, не предназначено. - person Kaiido   schedule 14.12.2016const
(вы получите точно такие же результаты сlet
), и я не используюconst
для изменяемых переменных - вы не можете этого сделать в совместимом браузере. Я используюconst
для постоянных переменных, относящихся к изменяемым объектам, что является совершенно отдельной (и нормальной в JS) вещью. В настоящее время JavaScript не имеет хорошей поддержки глубокой неизменяемости (Object.freeze
и тому подобное все еще оставляет дыры), и, хотя неизменяемость фантастична и полезна, это не единственный способ делать что-то. - person T.J. Crowder   schedule 17.12.2016foo.bar = function(){}
- это не тот же синтаксис, что иfoo={bar:function(){}}
, последнее называет функции, а первое - нет. у них явно разное поведение. Во всех случаях первое не изменит свойствоname
функции. Если бы он менял его только в случае, если свойство было равно, это был бы особый случай. Вот о чем вы спрашиваете. Это было бы непоследовательным поведением, так почему дизайнер должен явно оправдывать невыполнение этого? - person Chris Rollins   schedule 21.12.2016foo.bar = function(){}
не называет функцию.foo = function(){}
делает. В этом весь смысл вопроса. Есть что-то вроде полдюжины синтаксисов, использующих ранее анонимные выражения, которые затем присваиваются чему-то (переменной, свойству объекта во время инициализации объекта, значению параметра по умолчанию), которые делают, начиная с ES2015, присваивают имена . Есть одно вопиющее упущение. AWB сослался на возражения без подробного объяснения. Я хочу знать, какие они (или были). - person T.J. Crowder   schedule 22.12.2016