【问题标题】:Global JSON variable override全局 JSON 变量覆盖
【发布时间】:2012-05-02 18:23:42
【问题描述】:

我必须在我的项目中使用 json2.js,因为浏览器 (IE8) JSON 对象不可用于将字符串解析为 JSON。

我浏览了 json2.js 并且对变量声明有疑问。

A JSON global variable is declared in json2.js like

var JSON;
if(!JSON){
    JSON={};
}

声明var JSON;对全局JSON对象有什么影响。 我希望声明应该覆盖任何浏览器(IE8/IE7)中的全局 JSON 对象。 但令我惊讶的是,当全局对象可用时,它并没有覆盖。 只有变量定义/启动会覆盖全局变量? 请澄清。

【问题讨论】:

  • IE 8 has JSON 设置为标准模式
  • 但是我的 Intranet 网页(带有 JSF 和 Richfaces)总是以 IE7 模式加载。那是另一回事。

标签: javascript json scope


【解决方案1】:

对于每个变量声明(不是初始化!)。会发生以下情况 (section #10.5):

8。对于代码中的每个 VariableDeclarationVariableDeclarationNoIn d,按照源文本顺序执行

  1. dn成为d中的标识符
  2. varAlreadyDeclared 成为调用 env 的 HasBinding 具体方法并传递 dn 作为参数的结果。
  3. 如果 varAlreadyDeclaredfalse,则
    1. 调用 env 的 CreateMutableBinding 具体方法,传递 dnconfigurableBindings 作为参数。
    2. 调用 env 的 SetMutableBinding 具体方法,传递 dnundefinedstrict 作为参数。

所以你看,每当遇到var x 时,都会测试环境中是否已经存在名为x 的变量。如果是,则忽略它,但如果不是,则使用undefined 声明和初始化变量。

由于代码在全局范围内运行,它会测试JSON 是否存在于全局范围内。所以如果JSON 已经存在,var JSON; 就会被忽略。


关于测试/解释这种行为的一些想法:

我不知道在 JavaScript 执行的哪个时间点创建了全局对象,但我假设在评估所有其他脚本之前。这意味着,JSON 存在并且在任何变量声明之前都有一个值,只有包含两个脚本时才能模拟(我猜也可以是内联的,它们在另一个之后被评估)。 p>

试试:

// script1.js
var foo = 'bar';

// script2.js
var foo;
if(!foo) {
    foo = 'baz';
}
alert(foo);

// include script2.js after script1.js

结果如何? (cheaters look here)。


当您在单个脚本文件中时,所有变量声明无论如何都会被提升到顶部。所以如果你有

var foo = 'bar';
var foo;
if(!foo) {
    foo = 'baz';
}

脚本实际执行为:

var foo;
var foo;
foo = 'bar';
if(!foo) {
    foo = 'baz';
}

您实际上无法测试第二个var foo; 是否会覆盖第一个,因为此时它还没有任何价值。所以这不是一个很好的例子来展示上面引用的行为。

【讨论】:

    【解决方案2】:

    var 关键字确保在封闭函数中有一个变量,或者(像这里一样)在窗口中,但它不会初始化一个。

    事实上,顺序并没有真正的影响。

    以这段代码为例:

    a = 3;
    var a;
    alert(a);
    

    它会提示“3”。

    因此,您显示的代码中的 var 声明只是确保测试中不会出现错误,并且不会删除现有值。

    记住这一点是很好的,因为 javascript 中的一个常见错误是在一个函数中有多个 var 声明,并且对在 var 声明之前设置的值感到惊讶。例如运行这个:

    if (true) {
        ​a = 3;
    }
    // lot of code, at a different level
    if (true) {
        var a;
        if (433/43==3) a=true;
        if (a) alert('should not happen');
    };
    ​
    

    是的,var 附加到函数,而不是块...

    【讨论】:

    • 这里有点不同。在您的示例中,变量语句 hoisted 到顶部。所以即使你这样写,实际的执行顺序是var a; a = 3;(或者它可能是var a; a = 3; var a; (not hoisted),这也是有意义的,然后它就会适合)。在这种情况下,JSON 是环境中的预定义符号,在评估变量声明之前它已经有一个值(我假设)。我不知道,我只是想指出区别。
    【解决方案3】:

    这可能不是您的选择,但也可以将 IE8 设置为兼容模式以获取本机 JSON 对象:

    // in your preinit page event
    Response.AddHeader("X-UA-Compatible", "IE=8");
    

    另一种选择是仅当 JSON 变量不存在时才创建它:

    var JSON = JSON || {};
    

    【讨论】:

      【解决方案4】:

      如果您在执行该代码块时处于全局范围内,则 var JSON 会将全局 JSON 对象覆盖为 undefined。

      如果您在任何其他范围内(例如在函数内部),则不会有任何效果。

      【讨论】:

      • 通常脚本在全局范围内执行。那么为什么会出现呢?
      • 我的意思是:它在全局范围内执行,并且它不会覆盖全局JSON 对象(如果存在)。为什么要呢?那将是完全的浪费。
      猜你喜欢
      • 2013-05-27
      • 1970-01-01
      • 2015-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      相关资源
      最近更新 更多