【问题标题】:Why JSON is a subset of JavaScript?为什么 JSON 是 JavaScript 的子集?
【发布时间】:2016-02-05 11:18:46
【问题描述】:

Wikipedia says JSON 被设计为 JavaScript 的非严格子集,即添加允许使用一些 Unicode 字符。引用截至 2015-11-05 的当前版本:

虽然 JSON 通常被认为是 JavaScript 和 ECMAScript 的子集,但它允许在 JavaScript 和 ECMAScript 字符串中存在非法的字符串中的一些未转义字符。

但是.. 如果我将任何来自 Wikipedia 页面的示例粘贴到 ESLint 中,它会失败并出现错误。

例如我粘贴这个:

{
  "id": 1,
  "name": "Foo"
}

进入http://eslint.org/demo/ 并获取:

2:8 - 解析错误:意外令牌:(未定义)

由于某种原因,冒号在 JavaScript 中似乎是非法的,它与字符串中的未转义字符无关。

为什么人们仍将 JSON 称为 JavaScript 子集?

【问题讨论】:

  • 你的 JSON 是一个无效的 EcmaScript,但却是一个有效的 JSON。
  • 与其说是冒号,不如说是一个意外出现的对象。试试以var x = 为前缀。 (它会给你另一个错误,但它语法上没问题。)
  • 试试var obj = { "id": 1, "name": "Foo" }
  • 就像 var x=1 是 JS,并不意味着它可以在任何地方工作,例如 var y= var x=2

标签: javascript json eslint


【解决方案1】:

JSON 是 JavaScript object 表示法的子集。你不能凭空声明一个对象。

该对象的 JavaScript 用法是将其分配给一个变量:

var o = {
  "id": 1,
  "name": "Foo"
};

或将其传递给函数:

console.dir( {"id": 1, "name": "Foo" } );

等等

【讨论】:

    【解决方案2】:

    您遇到了一个有些常见的问题:松散的对象字面量被解释为一个块,而不是一个对象。

    如果在开头加上var foo =,则完全有效:

    var foo = {
      "id": 1,
      "name": "Foo"
    }
    

    如果没有var foo 来声明和初始化变量,解析器会看到一个块(如if (true) { ... })和字符串文字("id")。在松散的字符串文字之后冒号是不合法的,因为这在任何地方都不是真正的 JS:

    "id": foo(); // doesn't make sense
    

    这更常见于对象文字中未加引号的属性,解析器将其解释为命名标签(很少使用的 foo: 语法与 goto 一起使用)。构造

    {
      id: 1,
      name: "Foo"
    }
    

    看起来像一个带有标签id(指向表达式1)、逗号运算符和另一个标签的块。同样,这没有多大意义,但第一部分至少是合法的解析。

    因为您遵循 JSON 规范而不是 JS 对象字面量并引用了您的属性名称,所以它会将它们作为字符串字面量提取,并且无法从那里弄清楚该怎么做。

    有趣的是,如果你要使用:

    {
      "id".toString(),
      "name".substr(1)
    }
    

    那么 ESlint 不会抱怨。它很奇怪,也不是很有用,但却是一种完全合法的语言结构。

    【讨论】:

      【解决方案3】:

      问题是解析器还不能确定它是对象上下文。你可以把它包在()中:

      ({
          "id": 1,
          "name": "Foo"
      })
      

      它会做你所期望的。

      【讨论】:

        【解决方案4】:

        JSON 是一个子集,因为它仅用于数据。 JavaScript 允许定义函数和执行语句。 JSON 只允许定义数据。这就是为什么它是一个子集。

        您在尝试将 JSON 验证为 JavaScript statement 时收到的错误是您的数据不是 statement。将其转换为语句以在 eslint 上看不到错误:

        var foo = {
            "id": 1,
            "name": "Foo"
            };
        

        【讨论】:

        • 以上没有方法,JSON需要引用键,不能编码Date对象或RegExp,甚至不能使用对象引用;只有原语和文字。
        猜你喜欢
        • 2021-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-24
        相关资源
        最近更新 更多