(无效)如何在JSON中使用“this”关键字

时间:2013-10-29 13:07:49

标签: javascript

如何在下面的示例中使用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”。

3 个答案:

答案 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引用正在构造的新对象,然后自动从构造函数返回。