8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

对象字面量/初始化器中的自引用

maidan 2月前

84 0

有什么方法可以让下面的内容在 JavaScript 中工作吗?var foo = { a: 5, b: 6, c: this.a + this.b // 不起作用}; 在当前形式中,此代码显然通过......

有没有什么方法可以让下面的内容在 JavaScript 中运行?

var foo = {
    a: 5,
    b: 6,
    c: this.a + this.b  // Doesn't work
};

在当前形式下,此代码显然会引发引用错误,因为 th有 不引用 foo 。但是, is 没有办法让对象文字的属性中的值依赖于先前声明的其他属性?

帖子版权声明 1、本帖标题:对象字面量/初始化器中的自引用
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由maidan在本站《function》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 好吧,我唯一能告诉你的是 getter :

    var foo = {
      a: 5,
      b: 6,
      get c() {
        return this.a + this.b;
      }
    }
    
    console.log(foo.c) // 11

    这是 ECMAScript 第五版规范引入的语法扩展,大多数现代浏览器(包括 IE9)都支持该语法。

  • 非常有用的答案。有关“get”的更多信息,请参见此处:developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/…

  • 请注意,使用此解决方案,如果 foo.a 或 foo.b 的值发生变化,则 foo.c 的值也会同步变化。这可能是也可能不是所需的。

  • 请注意,这将绑定到最深的嵌套对象。例如:... x:{get c(){/*这是x,不是foo*/}}...

  • 为了完成上面的陈述,由于 foo 被声明为一个变量,并且 c 只会在调用时被评估,所以在 c 中使用 foo 是可行的,与此相反(但要小心)

  • 你可以做类似的事情:

    var foo = {
       a: 5,
       b: 6,
       init: function() {
           this.c = this.a + this.b;
           return this;
       }
    }.init();
    

    这将是对象的某种一次性初始化。

    init() 的返回值分配给 foo ,因此您必须 return this .

  • @BillyMoon:确实如此,尽管这样做会影响许多引擎(例如 V8)上该对象所有后续属性访问的性能。

  • @MuhammadUmer:类只是构造函数的语法糖,因此它们实际上并没有提供任何新东西。无论如何,这个问题的主要焦点是对象文字。

  • @akantoword:太棒了 :) 因为对象字面量是单个表达式,所以 init() 调用直接附加到字面量上,以保持它是单个表达式。但当然,如果您愿意,您可以单独调用该函数。

  • 缺少明显而简单的答案,因此,为了完整起见:

    但是 有没有 办法让对象文字的属性值依赖于先前声明的其他属性?

    不。这里的所有解决方案都将其推迟到创建对象之后(以各种方式),然后再分配第三个属性。 最简单的 方法就是这样做:

    var foo = {
        a: 5,
        b: 6
    };
    foo.c = foo.a + foo.b;
    

    所有其他方法都只是更间接地完成相同任务的方法。(Felix 的方法特别聪明,但需要创建和销毁临时函数,这增加了复杂性;并且要么在对象上留下额外的属性,要么 [如果您有 delete 该属性] 该对象后续属性访问的 性能

    如果您需要将其全部放在一个表达式中,则可以不使用临时属性来做到这一点:

    var foo = function(o) {
        o.c = o.a + o.b;
        return o;
    }({a: 5, b: 6});
    

    或者当然,如果你需要多次执行此操作:

    function buildFoo(a, b) {
        var o = {a: a, b: b};
        o.c = o.a + o.b;
        return o;
    }
    

    然后你需要在哪里使用它:

    var foo = buildFoo(5, 6);
    
  • GAVD 2月前 0 只看Ta
    引用 12

    为了我自己的理智,我试图找到某种官方文档,它基本上说了同样的事情 - 对象的 this 仅适用于该对象的方法,而不适用于其他类型的属性。知道我在哪里可以找到它吗?谢谢!

  • @DavidKennell:没有比规范更正式的了。:-) 您可能会从这里开始并遵循它。这是相当尴尬的语言,但基本上您会在属性定义评估的各个子句中看到,该对象不可用于确定属性初始化器值的操作。

  • 我在这里看不到浏览器范围的结果,但情况不再如此,对吧?在我的环境中,v8: delete 快 10%,而 gecko: delete 慢 1%。

  • sliq 2月前 0 只看Ta
    引用 15

    @TheMaster - 是的,我认为 BrowserScope 已经不复存在了。删除似乎没有以前那么麻烦了,至少在 V8(Chrome 等)或 SpiderMonkey 中不是这样。速度仍然较慢,但只是一点点,而且现在这些东西的速度快得惊人。

  • 只需实例化一个匿名函数:

    var foo = new function () {
        this.a = 5;
        this.b = 6;
        this.c = this.a + this.b;
    };
    
  • @Bergi,为什么?因为有人可能会从中实例化另一个相同的对象?这并不是说他们不能直接克隆对象文字。这与传递 new Point(x, y) 之类的参数没有什么不同,只是函数没有被命名为可重用。

  • @zzzzBov:当然他们可以克隆对象,但与 IEFE 解决方案(如 TJCrowder 的答案)相比,您的解决方案泄漏了构造函数并创建了一个多余的原型对象。

  • 引用 19

    @zzzzBov:只需使用 var foo = function() { this.…; return this; }.call({}); 从语法上讲没有太大区别,但从语义上讲是合理的。

  • 现在,在 ES6 中,您可以创建延迟缓存属性。首次使用时,该属性将求值一次,成为普通静态属性。结果:第二次跳过数学函数开销。

    魔法就在吸气者身上。

    const foo = {
        a: 5,
        b: 6,
        get c() {
            delete this.c;
            return this.c = this.a + this.b
        }
    };
    

    在箭头中,getter this 拾取 周围的词法范围 .

    foo     // {a: 5, b: 6}
    foo.c   // 11
    foo     // {a: 5, b: 6 , c: 11}  
    
返回
作者最近主题: