为什么`obj.foo = function(){};`不将名称`foo`分配给函数?

T.J*_*der 53 javascript function ecmascript-6

从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
Run Code Online (Sandbox Code Playgroud)

但是,在对象初始值设定项之外的现有对象上分配属性不会:

const obj = {};
obj.foo = function() { };
console.log("Nope:", obj.foo.name);
Run Code Online (Sandbox Code Playgroud)

据我所知,这是所涵盖这一部分的规范,其中明确只设置函数名,如果IsIdentifierRef中的LeftHandSideExpression为真(这显然是不为属性引用).

从上面重申:为什么不呢?当然必须有一个特定的理由,这是不可取的/可能的.它以前如何?

T.J*_*der 15

Allen Wirfs-Brock 在es-discuss列表中回复了反对意见,这些异议阻止了TC39在obj.foo = function() { }表格上的共识:

...对于

cache[getUserSecret(user)] = function() {};
Run Code Online (Sandbox Code Playgroud)

它会泄露秘密用户信息作为名称的值

并为

obj[someSymbol] = function() {}
Run Code Online (Sandbox Code Playgroud)

它会将Symbol值作为name的值泄漏

并为

 table[n]=function() {}
Run Code Online (Sandbox Code Playgroud)

name可能是一个数字字符串

这些异议有一些反驳(特别是最后一个,这是非常弱的;还有很多其他方法可以自动为函数分配一个数字字符串名称),但这不是重点; 关键是那些是提出的异议.

他还补充说,需要IsPropertyReference操作(目前只有IsIdentifierRef)...

...是运行时操作,新语义需要运行时确定名称值.这是额外的运行时工作,可能会减慢循环中出现的函数闭包的创建速度.

总而言之,显然在做出决定的时候,那些反对意见在当天进行(现在很可能也会如此),这就是为什么这种形式不会自动命名功能而其他许多人都这样做的原因.