有什么方法可以让下面的东西在JavaScript中工作?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
在当前的表单中,这段代码显然抛出了一个引用错误,因为它没有引用foo。但是有没有办法让对象字面量的属性值依赖于之前声明的其他属性呢?
有什么方法可以让下面的东西在JavaScript中工作?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
在当前的表单中,这段代码显然抛出了一个引用错误,因为它没有引用foo。但是有没有办法让对象字面量的属性值依赖于之前声明的其他属性呢?
当前回答
你可以这样做
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的日志。
其他回答
可维护性很好的替代语法:
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 foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
其他的都是做同样事情的更间接的方式。(Felix的方法特别聪明,但需要创建和销毁临时函数,这增加了复杂性;并且要么在对象上留下额外的属性,要么[如果删除该属性]影响该对象上后续属性访问的性能。)
如果你需要它都在一个表达式中,你可以不使用temporary属性:
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);
在对象字面量上创建新函数并调用构造函数似乎与原始问题完全不同,而且没有必要。
在对象文字初始化期间不能引用兄弟属性。
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
计算属性的最简单的解决方案如下(没有堆,没有函数,没有构造函数):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
注意:这个解决方案使用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';
};
}
}
这里有一个简洁的ES6方法:
Var foo = (o => ({ ……啊, C: o.a + o.b ({})) 5, b: 6 }); console.log (foo);
我用它来做这样的事情:
const常量= Object.freeze( (_ => ({ _, flag_data: { (_。a_flag]:“foo”, (_。b_flag]:“酒吧”, [_.c_flag]:“力量” } ({})) a_flag: 5 b_flag: 6, c_flag: 7, }) ); console.log (constants.flag_data [constants.b_flag]);