为什么`obj.foo = function() { };` 没有将名称`foo` 分配给函数? [英] Why does `obj.foo = function() { };` not assign the name `foo` to the function?

查看:13
本文介绍了为什么`obj.foo = function() { };` 没有将名称`foo` 分配给函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从 ES2015 (ES6) 开始,函数有专有名称(包括官方的 name 属性),除了明显的函数声明之外,函数创建时还会以多种方式分配名称和命名函数表达式,例如赋值给变量(函数名设置为变量名),赋值给对象属性(函数名设置为属性名),甚至函数参数的默认值(函数名设置为参数名)名称).但是分配给现有对象上的属性(例如,不在对象初始值设定项中)不会将该属性的名称分配给函数.为什么不?肯定有一个特定的原因,它是不可取的/不可能的.那是什么?

明确地说:我不是在问如何解决它.我在问是什么阻止了这个看似明显的案例在这么多其他案例(包括默认参数值!)的情况下被处理.一定有充分的理由.

请不要推测或理论化. TC39 不包括它是有原因的.我对那个原因很感兴趣.我已经阅读了 TC39 会议笔记,但还没有找到.到目前为止我找到的最接近的是 Allen Wirfs-Brock 回复 Bergi 说由于各种反对意见",未能就该表格达成共识,但遗憾的是,他没有说明这些反对意见是什么.

详情:

以下所有将名称 foo 分配给 上的函数兼容浏览器:

//需要兼容的浏览器//赋值给一个变量或常量...//...无论是在初始化...{让 foo = function() { };console.log("1:", foo.name);//"富"}{const foo = function() { };console.log("2:", foo.name);//"富"}//...或以后...{让 foo;foo = 函数() { };console.log("3:", foo.name);//"富"}//作为对象属性的初始化器{常量对象 = {富:函数(){}};console.log("4:", obj.foo.name);//"富"}//或者作为一个方法{常量对象 = {foo() { }};console.log("5:", obj.foo.name);//"富"}//即使它是一个计算属性名称{让名字=f";常量对象 = {[姓名 + "o" + "o"]() { }};console.log("6:", obj.foo.name);//"富"}//作为参数的默认值(函数(foo = 函数(){}){console.log("7:", foo.name);//"富"})();//...还有其他一些

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

const obj = {};obj.foo = function() { };console.log("Nope:", obj.foo.name);

据我所知,这包含在 本部分 规范,如果 LeftHandSideExpressionIsIdentifierRef 为真(显然 它不是用于属性引用).

所以从上面重申:为什么不呢?肯定有一个特定的原因,它是不可取的/不可能的.那是什么?

解决方案

Allen Wirfs-Brock 拥有 在 es-discuss 列表中回复 反对阻止 TC39 就 obj.foo = function() { } 形式达成共识:<块引用>

...为了

cache[getUserSecret(user)] = function() {};

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

为了

obj[someSymbol] = function() {}

它会泄漏 Symbol 值作为 name 的值

为了

 table[n]=function() {}

name 可能是一个数字字符串

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

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

<块引用>

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

总而言之,显然在做出决定时,这些反对意见占据了上风(现在很可能也是如此),这就是为什么这种形式不会自动命名函数,而其他许多人会这样做.

As of ES2015 (ES6), functions have proper names (including an official name property), and names are assigned when the function is created in a variety of ways in addition to the obvious function declaration and named function expression, such as assigning to variables (function's name is set to the variable's name), assigning to object properties (function's name is set to the property's name), even default values for function parameters (function's name is set to the parameter's name). But assigning to a property on an existing object (e.g., not in an object initializer) doesn't assign that property's name to the function. Why not? Surely there must be a specific reason it was not desirable/possible. What was it?

To be clear: I'm not asking how to work around it. I'm asking what prevents this seemingly-obvious case from being handled when so many others (including default parameter values!) are. There must be a good reason.

Please don't speculate or theorize. TC39 had a reason for not including it. I'm interested in what that reason was. I've been through the TC39 meeting notes but haven't found it yet. The closest I've found so far is Allen Wirfs-Brock replying to Bergi to say there was no consensus for doing it for that form because of "various objections," but sadly he didn't say what those objections were.

Details:

All of the following assign the name foo to the function on a compliant browser:

// 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

But assigning to a property on an existing object, outside an object initializer, does not:

const obj = {};
obj.foo = function() { };
console.log("Nope:", obj.foo.name);

As far as I can tell, this is covered by this section of the specification, which explicitly only sets the function name if the IsIdentifierRef of the LeftHandSideExpression is true (which apparently it isn't for property references).

So reiterating from above: Why not? Surely there must be a specific reason it was not desirable/possible. What was it?

解决方案

Allen Wirfs-Brock has replied on the es-discuss list with the objections that prevented the TC39 consensus on the obj.foo = function() { } form:

...for

cache[getUserSecret(user)] = function() {};

it would leak the secret user info as the value of name

and for

obj[someSymbol] = function() {}

it would leak the Symbol value as the value of name

and for

 table[n]=function() {}

name would likely be a numeric string

There are counters to those objections (particularly the last one, which is extremely weak; there are many other ways a function is automatically assigned a numeric string name), but that's not the point; the point is that those were the objections raised.

He also added that the IsPropertyReference operation that would be required (where currently there's just an IsIdentifierRef)...

...is a runtime operation and the new semantics require runtime determination of the name value. This is all extra runtime work that may slow down the creation of function closures that appear within loops.

So all in all, apparently at the time the decision was taken, those objections carried the day (and quite possibly would now as well), which is why this form doesn't automatically name functions whereas so many others do.

这篇关于为什么`obj.foo = function() { };` 没有将名称`foo` 分配给函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆