如果我理解它,这实际上可能不是一个无效的问题(只是一个问得不好,有一些错误的问题),并且真的可能有点有趣。JSON 用词不当是一个令人分心的不幸错误,但实际上,他在问如何动态地让一个属性等于其他属性的动态结果——即,为什么不
x = {
a: "hello",
b: " ",
c: "world",
d: this.a + this.b + this.c
}
导致
x.d === "hello world"
?
相反,您发现的是this
指window
那里。这向我们展示了这this
只是从函数内部获得的东西,而不是我们可以在该上下文之外依赖的内在关系引用。
这显然是为什么提问者然后使用一个函数来访问this
. 但是,我认为问题在于你得到了一个你必须调用的函数,他实际上想要文本。(我可能会在那里推断一下,不确定。)
有人可能会想只使用 IIFE,但这也行不通:
x = {
a: "hello",
b: " ",
c: "world",
d: (function() { this.a + this.b + this.c })()
}
x.d === NaN // undefined + undefined + undefined
发生的情况是,当我们调用 IIFE 时,我们创建了一个新的作用域,带有一个新的this
-- 而且,它只会在对象初始化时运行一次,并且不会动态地反映那些其他值的变化。
因为他说'我们必须将对象分配给一个变量然后使用它',所以我认为他找到了一种解决方法,您只需声明它两次,如果您指的是全局属性,第二次它就可以工作(所以,x.a + x.b
),并提供了错误的例子。
所有这些都表明词法作用域在这里超越了动态作用域。人们可能会考虑尝试解决此问题的另一种天真方式是这样的:
x = {
a: "hello",
b: " ",
c: "world",
d: (function() { this.x.a + this.x.b + this.x.c })()
// or maybe:
e: (function() { this.x.a + this.x.b + this.x.c }).call(this)
}
(解释:因为this
指的是window
和x
是一个全局的,因此是window
(ie, window.x === x
) 的属性......老实说,我们也可以在this
这里省略,但它有助于说明这里发生了什么,所以我会留下它。)
但是不,该函数x
在初始化时被调用,因此x
直到该函数调用之后才在词法范围内定义。或者e
,'this' 仍然是window
。
我们在这里了解到的是,在 Javascript 中评估对象时也无法访问同级属性。
整洁的!
因此,要实现预期目标,需要两个单独的语句:
x = {
a: "hello",
b: " ",
c: "world"
}
x.d = x.a + x.b + x.c;
除非您希望 xd 能够以这些值动态响应,而不是此时添加这些值的结果 - 那么您只需使用问题中的原始代码,并且必须将其作为函数进行评估。
……
写完上面的内容后,我想起了一个我从未使用过的 JavaScript 特性:getter 和 setter。果然,他们完成了我们在这里寻找的东西:
var hello = {
a: "hello",
b: "world",
get test() {
return this.a + this.b
}
}
// undefined
hello.test
// "helloworld"
hello.a = 'stuff'
// "stuff"
hello.test
// "stuffworld"
当然,这在计算上等价于调用 hello.test() 并将 test 设为函数,就像在原始代码中一样。这个 getter 不能像函数一样被序列化,就 JSON 而言(尽管我们确定这不是重点,我只是想清楚一点)。最后,我们真正获得的唯一东西是省略括号的能力——而且这不会通过 JSON 序列化,要明确的是,如果这真的是问题的故意部分。