name
属性),并且在创建函数时以各种方式分配名称,除了明显的函数声明和命名函数表达式外,还可以将名称分配给变量(函数的名称设置为变量的名称)、将名称分配给对象属性(函数的名称设置为属性的名称),甚至是函数参数的默认值(函数的名称设置为参数的名称)。但是在现有对象上分配属性(例如不在对象初始化中)不会将该属性的名称分配给函数。为什么呢?肯定有一个特定的原因不希望或不可能这样做。那是什么原因呢?明确一下:我不是在询问如何解决此问题。我想知道是什么阻止了处理这种看似明显的情况,而其他许多情况(包括默认参数值!)都能够被处理。肯定有一个很好的原因。
请不要猜测或推理。 TC39没有包含它的原因。我对那个原因很感兴趣。我已经查看了TC39会议记录,但还没有找到。到目前为止,我找到的最接近的是Allen Wirfs-Brock 回复Bergi说,由于“各种反对意见”,没有就那种形式达成共识。但遗憾的是,他没有说出这些反对意见是什么。
细节:
以下所有内容都将名称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);
因此,重申上文:为什么不这样做呢?肯定有一个具体的原因,不可取/不可能。是什么原因呢?
obj.prop1
和obj.prop2
都被赋值为function() {}
,应该为此赋予什么名称?不做任何归属很方便地避免回答这类有争议的问题。 - artemvar x = y = function() ...
,我看到的第一个名称是var x
,因此函数被命名为y
可能会令人困惑,并且可能被视为一个错误。我认为在创建函数时分配名称的正确方法是使用明确的命名函数语法:var x = y = function y() {}
- artemx = y = function() { };
这个语句在语言运作上完全合理且一致。它会先评估y = function() { }
(创建函数,给它命名,把它分配给y
),然后将这个结果值(一个已存在的函数引用)分配给x
。做其他任何事情都会违反标准表达式语义,并需要极其复杂的机制才能实现。 - T.J. Crowder