有什么方法可以让下面的东西在JavaScript中工作?

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

在当前的表单中,这段代码显然抛出了一个引用错误,因为它没有引用foo。但是有没有办法让对象字面量的属性值依赖于之前声明的其他属性呢?


当前回答

现在在ES6中,你可以创建惰性缓存属性。在第一次使用时,该属性只计算一次,成为一个正常的静态属性。结果:第二次跳过数学函数开销。

神奇之处在于getter。

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

在箭头getter中,这将拾取周围的词法作用域。

foo     // {a: 5, b: 6}
foo.c   // 11
foo     // {a: 5, b: 6 , c: 11}  

其他回答

我使用下面的代码作为替代,它工作。变量也可以是array。(@福斯托R.)

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

  d: [10,20,30],
  e: function(x) {
    this.d.push(x);
    return this.d;
  }
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]

如果你想使用原生JS,其他答案提供了很好的解决方案。

但是如果你愿意写自引用对象,比如:

{ 
  a: ...,
  b: "${this.a + this.a}",
}

我写了一个叫做self- references -object的npm库,它支持这种语法并返回一个原生对象。

这个解决方案如何?它也适用于带有数组的嵌套对象

      Object.prototype.assignOwnProVal
     = function (to,from){ 
            function compose(obj,string){ 
                var parts = string.split('.'); 
                var newObj = obj[parts[0]]; 
                if(parts[1]){ 
                    parts.splice(0,1);
                    var newString = parts.join('.'); 
                    return compose(newObj,newString); 
                } 
                return newObj; 
            } 
            this[to] = compose(this,from);
     } 
     var obj = { name : 'Gaurav', temp : 
                  {id : [10,20], city:
                        {street:'Brunswick'}} } 
     obj.assignOwnProVal('street','temp.city.street'); 
     obj.assignOwnProVal('myid','temp.id.1');

可维护性很好的替代语法:

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

这是因为如果您没有显式地指定名称,JavaScript将使用变量名作为新创建的对象的属性名。对于像这样的短数组,如果在函数中,我个人会使用单行语法和return:

let a = 5;
let b = 6;
return { a, b, c:a+b };

你可以这样做

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

当我必须引用函数最初声明的对象时,该方法已被证明对我有用。以下是我如何使用它的一个最小示例:

function createMyObject() {
    var count = 0, self
    return {
        a: self = {
            log: function() {
                console.log(count++)
                return self
            }
        }
    }
}

通过将self定义为包含print函数的对象,允许函数引用该对象。这意味着如果您需要将print函数传递到其他地方,则不必将其“绑定”到对象。

如果您愿意,可以使用下面所示的方法

function createMyObject() {
    var count = 0
    return {
        a: {
            log: function() {
                console.log(count++)
                return this
            }
        }
    }
}

然后下面的代码将记录0,1,2,然后给出一个错误

var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!

通过使用self方法,可以保证print总是返回相同的对象,而不管函数在什么环境中运行。当使用createMyObject()的self版本时,上面的代码将正常运行并记录0、1、2和3的日志。