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

(invalid) How to use the "this" keyword in JSON

本文关键字:this 关键字 JSON 无效      更新时间:2023-09-26

如何在下面的示例中的JavaScript对象表示法(JSON)中使用"this"关键字?

{
    firstName: "Foo",
    lastName: "Bar",
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}

上面的代码既不适用于 this 关键字,也不适用于它。为什么?唯一有效的解决方案是将 JSON 对象分配给变量并在代码中使用该变量。

是否有类似于"this"关键字的东西可以用来代替它?

欢迎任何建议。

编辑:如下面的评论中所述,它不是JSON,而是"javascript对象文字"。谢谢你的提示。尽管如此,我的问题仍然有效(对于 javascript 对象文字)。

无效:上面的代码按预期工作,因此 fullName() 返回 "Foo Bar"。

如果我理解它,这实际上可能不是一个无效的问题(只是一个问得不好的问题,有一些错误),而且真的可能有点有趣。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的属性(即window.x === x)......老实说,我们也可以在这里省略this,但它有助于说明这里发生的事情,所以我会离开它。

但是不,该函数是在初始化x时调用的,因此直到该函数调用之后x才在词法范围内定义。 或e,"这个"仍然window

我们在这里学到的是,在Javascript中对象的求值时,也无法访问同级属性。

整洁!

因此,要实现预期目标,需要两个单独的语句:

x = {
  a: "hello",
  b: " ",
  c: "world"
}
x.d = x.a + x.b + x.c;

除非你希望能够让 x.d 动态响应这些值,而不是此时添加这些值的结果,否则你只需要使用问题中的原始代码,并且必须将其作为一个函数进行评估。

。...

当我写完上面的内容后,我想起了一个我从未使用过的javascript功能:getters和setters。果然,它们完全实现了我们在这里寻找的目标:

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 不能像函数一样序列化(尽管我们确定这不是这里的重点,我只是想说清楚)。最后,我们唯一真正获得的是省略括号的能力 - 而且这不会在JSON上序列化,需要明确的是,如果这真的是问题的有意部分。

代码存在多个问题。比this问题更基本的是JSON甚至不能包含函数(请记住,JSON被Javascript以外的语言使用!)。它纯粹是一个数据传输系统。

并非所有可以成为 Javascript 对象一部分的对象都可以在 JSON 中序列化。

"上面的代码既不适用于这个关键字,也不适用于它。这是为什么呢?

虽然您谈论的是 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引用正在构造的新对象,然后自动从构造函数返回该对象。