有什么方法可以让下面的东西在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。但是有没有办法让对象字面量的属性值依赖于之前声明的其他属性呢?
当前回答
我使用下面的代码作为替代,它工作。变量也可以是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]
其他回答
如果你的对象被编写成一个返回对象的函数,并且你使用ES6对象属性“方法”,那么它是可能的:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
我唯一能告诉你的是getter
Var foo = { 5, b: 6, 获取c() { 返回。A + this.b; } } Console.log (foo.c) // 11
这是由ECMAScript第5版规范引入的一个语法扩展,大多数现代浏览器(包括IE9)都支持该语法。
注意:这个解决方案使用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';
};
}
}
加上一个选项,因为我没有看到这种情况。如果您不希望在a或b更新时更新c,那么ES6 IIFE可以很好地工作。
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
对于我的需要,我有一个对象,涉及到一个数组,最终将在循环中使用,所以我只想计算一些常见的设置一次,所以这是我有:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
因为我需要为indexOfSelectedTier设置一个属性,我需要在设置hasUpperTierSelection属性时使用该值,我首先计算该值,并将其作为参数传递给IIFE
好吧,我想到了另一个解决方案。这里我想初始化一个对象,表示每个时间单位的毫秒数。 结果是typescript中的enum在我的例子中不能使用,所以我声明了多个变量,并将其分配给一个对象,如下所示:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
这种方法的缺点是:
变量被定义为常量,即使我们不需要它们。因此它需要无用的内存。 对象的每个值必须声明为独立的变量