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

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

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


当前回答

简单地实例化一个匿名函数:

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

其他回答

我使用下面的代码作为替代,它工作。变量也可以是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]

我认为下面的代码对于可维护性来说是最好的,尽管它不是在对象文字语法中:

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

这将使用{}创建一个新的空对象,然后使用匿名函数设置其属性(使用call()执行)。我认为唯一不好的部分是需要返回这个,感觉像是多了一行代码。不幸的是,我不能想出任何更好的方法来移动引用新创建的匿名对象到foo。

我认为这比语法var foo = new function(){…}因为它不会在原型链中创建一个额外的级别,就像@Bergi在一个现有答案的评论中解释的那样。

然而,如果这是真正的字面意思,没有任何其他逻辑,只有一个添加,它将更有意义的只是写

const foo = {
    a:5,
    b:6,
    c:11, // sum of a + b
};

因为不需要在运行时甚至编译时计算这个和。

注意:这个解决方案使用Typescript(如果需要,你可以使用TS编译的普通JS)

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

    // this method is just to check/test this solution 
    check(){
        console.log(this.def.qwe);
    }
}

// these two lines are just to check
let instance = new asd();
instance.check();

这里我们使用类表达式来获得我们想要的嵌套对象文字接口。以我之见,这是在创建过程中能够引用对象属性的下一个最好的事情。

主要需要注意的是,在使用此解决方案时,您将获得与从对象字面量获得的完全相同的接口。而且语法非常接近对象文字本身(相对于使用函数等)。

比较以下内容

我提出的解决方案

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

解决方案,如果对象字面量就足够了

var asd = {
    def : {
        ads:'asd',
        qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
    }
}

另一个例子

在这个类中,您可以组合它们之间的多个相对路径,这在对象字面量中是不可能的。

class CONSTANT {
    static readonly PATH = new class {
        /** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
         *
         */
        private readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
            readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
            readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
        };
    }
}

这一切的关键是SCOPE。

您需要将想要定义的属性的“父”(父对象)封装为它自己的实例化对象,然后可以使用关键字this引用同级属性

记住这一点非常非常重要,如果你没有先这么做就引用了这个,那么这个就会引用外部作用域。这将是窗口对象。

var x = 9   //this is really window.x
var bar = {
  x: 1,
  y: 2,
  foo: new function(){
    this.a = 5, //assign value
    this.b = 6,
    this.c = this.a + this.b;  // 11
  },
  z: this.x   // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};

您可以使用模块模式来实现这一点。就像:

var foo = function() {
  var that = {};

  that.a = 7;
  that.b = 6;

  that.c = function() {
    return that.a + that.b;
  }

  return that;
};
var fooObject = foo();
fooObject.c(); //13

使用这个模式,你可以根据需要实例化几个foo对象。

http://jsfiddle.net/jPNxY/1/