如何在下面的示例中使用JavaScript对象表示法(JSON)中的“this”关键字?
{
firstName: "Foo",
lastName: "Bar",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
上面的代码既不适用于this
关键字也不适用。
这是为什么?唯一可行的解决方案是将JSON对象分配给变量并在代码中使用该变量。
是否有类似于“this”关键字的东西可以用来代替呢?
欢迎任何建议。
编辑 如下面的评论中所述,它不是JSON而是“javascript object literal”。谢谢你的提示。不过,我的问题仍然有效(对于javascript对象文字)。
无效: 上面的代码按预期工作,因此fullName()返回“Foo Bar”。
答案 0 :(得分:6)
如果我理解,这实际上可能不是一个无效的问题(只是一个问题不好,有一些错误),并且真的可能有点有趣。 JSON用词不当是一个令人遗憾的令人分心的错误,但实际上,他要问如何动态地使一个属性等于其他属性的动态结果 - 即,为什么没有&#tt
x = {
a: "hello",
b: " ",
c: "world",
d: this.a + this.b + this.c
}
结果
x.d === "hello world"
相反,你发现的是这个'指那里的窗户。这向我们展示了这个'只是从函数内部获得的东西,而不是我们可以在该上下文之外依赖的内在关系引用。我不得不承认,当我意识到这一点并且正在玩这个看起来有点太明显的问题时,我有点惊讶。
这显然是为什么提问者随后使用了一个函数来访问这个'。但是,我认为问题是你需要调用一个函数,他实际上想要文本。 (我可能会在那里推断一下,不确定。)
人们很想尝试使用IIFE,但这也不会起作用:
x = {
a: "hello",
b: " ",
c: "world",
d: (function() { this.a + this.b + this.c })()
}
x.d === NaN // undefined + undefined + undefined
当我们调用IIFE时,我们会创建一个新的范围,并使用新的this
。
因为他说'我们必须将对象分配给一个变量,然后使用那个',我以为他找到了一个解决方法,你只需要声明它两次,如果你和& #39;重新引用全局属性(因此,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)
}
但是没有,在函数调用之后,x还没有在词法范围内定义,对于e
来说,'这个'仍然是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作为函数,就像在原始代码中一样。就JSON而言,这个getter不能像函数一样被序列化(尽管我们确定这不是重点,我只是想清楚)。最后,我们真正获得的唯一能力是省略括号。
答案 1 :(得分:5)
代码存在多个问题。比this
的问题更基本的是JSON甚至不能包含函数(请记住,JSON不是由Javascript使用的语言!)。它纯粹是一种数据传输系统。
并非所有可以作为Javascript对象一部分的对象都可以用JSON序列化。
答案 2 :(得分:3)
“上面的代码既没有使用this关键字,也没有使用它。为什么会这样?”
虽然您在谈论JSON时,在阅读问题文本时,听起来就像是在使用对象文字语法时如何使用this
在创建对象时引用该对象。
this
不适合你的原因是它的值只在一个函数中定义,定义它的是如何调用函数。
虽然你的代码确实提供了一个函数,但它在创建过程中无法引用该对象,因为在之后文字语法之前没有可用的引用。
“唯一可行的解决方案是将JSON对象分配给变量并在代码中使用该变量。”
没错,您不能在对象文字语法中使用this
来引用新对象,因此您需要在之后使用变量引用。
虽然作为文字语法的替代方法,但您可以使用构造函数来创建对象。这样,在创建对象后,您不需要使用该变量来创建fullName
属性。
var obj = new function() {
this.firstName = "Foo";
this.lastName = "Bar";
this.fullName = this.firstName + " " + this.lastName;
};
如果您将对象传递给函数,这也很有用。
my_func(new function() {
this.firstName = "Foo";
this.lastName = "Bar";
this.fullName = this.firstName + " " + this.lastName;
});
因此,您可以使用this
的原因是,如上所述,this
是在函数中定义的,并且是根据函数的调用方式定义的。
这里我们使用匿名函数作为构造函数,通过使用new
调用它。这使this
引用正在构造的新对象,然后自动从构造函数返回。