var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
在当前形式下,这段代码显然会抛出引用错误,因为
this
并不指向foo
。但是是否有任何方法可以使对象字面量属性中的值依赖于之前声明的其他属性呢?var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
this
并不指向foo
。但是是否有任何方法可以使对象字面量属性中的值依赖于之前声明的其他属性呢?嗯,我能告诉你的唯一事情就是有关getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
这是ECMAScript第5版规范引入的一种语法扩展,该语法得到大多数现代浏览器(包括IE9)的支持。
你可以尝试这样做:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
这将是对象的一次初始化。
请注意,您实际上正在将 init()
的返回值分配给 foo
,因此您必须返回this
。
return this
之前加上delete this.init
,这样就不会污染foo
。 - Billy Mooninit()
调用直接将字面量附加在其后,使其仍然保持单个表达式。但是,如果你想的话,当然可以单独调用该函数。 - Felix Kling显而易见,简单的答案丢失了,所以为了完整起见:
但是,有没有办法让对象字面量属性中的值依赖于先前声明的其他属性呢?
没有。所有这里的解决方案都是在对象创建后(以各种方式)推迟它,然后分配第三个属性。最简单的方法是只需执行以下操作:
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);
this
只能在该对象的 方法 中使用,而不能用于其他类型的属性。你知道在哪里可以找到吗?谢谢! - David Kennell只需实例化一个匿名函数:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
var foo = function() { this.…; return this; }.call({});
,语法上并没有太大的不同,但语义上是合理的。 - Berginew
关键字。你能行的。 - Randy现在在ES6中,您可以创建懒惰缓存属性。第一次使用时,该属性会评估一次以成为正常的静态属性。结果:第二次跳过了数学函数的开销。
神奇之处在于getter方法。
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
在箭头函数中,this
会捕获周围的词法作用域。foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Object.defineProperty(foo, 'c', {get:function() {...}})
来定义它们。在这样的工厂中,可以轻松地以不显眼的方式完成此操作。当然,如果您可以使用get
语法糖,那么代码更易读,但是该功能一直存在。 - Aluan Haddaddelete this.c
,但是它没有起作用。 - Ahsan Aliidelete
操作感到困惑。我认为它的作用是从对象中删除 get c
属性,并用标准属性覆盖它。我认为这样做只会计算一次,然后如果稍后更改 a
或 b
,foo.c
将不会更新其值,但这也仅在调用 foo.c
时起作用/缓存/计算。 - CTS_AEdelete this.c
的目的是删除 getter 并将其替换为单个数字值。 这样做可以避免每次使用 foo.c
时需要执行 getter。 return
语句既创建了替代属性 foo.c
,又返回了其值。 虽然有可能使用get c() { return this.a + this + b }
,但这会导致每次使用 foo.c
都重新评估。 - Mikko Rantalainen有些闭包应该处理这个问题;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
foo
中声明的所有变量都是私有的,这符合任何函数声明的预期,因为它们都在作用域内,所以它们可以相互访问而不需要引用this
,就像函数一样。不同之处在于,此函数返回一个公开私有变量并将该对象分配给foo
的对象。最终,您使用return {}
语句仅返回要作为对象公开的接口。
然后使用()
在结尾处执行函数,导致整个foo
对象被评估,实例化其中所有的变量,并将返回对象添加为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定义为包含打印函数的对象,您允许该函数引用该对象。这意味着如果您需要将其传递到其他地方,则无需将打印函数绑定到对象。
如果您使用下面所示的this
,则会......
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始终返回同一个对象。使用self版本的createMyObject()
函数,上述代码将正常运行并输出0、1、2和3。
为了完整性,在ES6中我们有类(在撰写本文时仅由最新浏览器支持,但可在Babel、TypeScript和其他编译器中使用)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
思考之所在——将对象的属性从时间轴中分离出来:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
上面有更好的答案。这是我修改了你质疑的示例代码的方式。
更新:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }
,所以现在您只需执行foo.c
而不是foo.c()
:)(随意将其粘贴到您的答案中,以便格式更好!) - user993683foo.c
。这可能是您要寻找的,也可能不是。 - Mikko Rantalainen
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.c
是一个函数,因此对其进行写入会覆盖该函数,并且通过fooObject.c()
的下一次调用将失败。也许这个fiddle更接近你想要的(它也是单例,不是为了实例化而设计的)。 - Hollister
foo.a
或foo.b
的值,则foo.c
的值也将同步更改。这可能是所需的,也可能不是所需的。 - HBPthis
绑定到最深层嵌套的对象。例如:... x: { get c () { /*这里的this是x,不是foo*/ } } ...
- Bernardo Dal Cornofoo
被声明为一个变量,并且c
只会在调用时被计算,因此在c
内部使用foo
是有效的,而不像使用this
(但请小心)。 - Bernardo Dal Corno