gpt4 book ai didi

javascript - Javascript中变量声明语法的区别(包括全局变量)?

转载 作者:行者123 更新时间:2023-12-01 17:18:44 24 4
gpt4 key购买 nike

声明一个变量有什么区别:

var a=0; //1

...这样:
a=0; //2

...或:
window.a=0; //3

在全局范围内?

最佳答案

是的,有一些差异,但实际上它们通常不是很大。

还有第四种方式,从 ES2015 (ES6) 开始,还有两种方式。我在最后添加了第四种方式,但在 #1 之后插入了 ES2015 方式(你会明白为什么),所以我们有:

var a = 0;     // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4

这些声明解释了

#1 var a = 0;

这将创建一个全局变量,它也是 global object 的一个属性。 ,我们访问为 window在浏览器上(或通过 this 全局范围,在非严格代码中)。与其他一些属性不同,该属性不能通过 delete 删除。 .

在规范方面,它在对象 Environment Record 上创建了一个标识符绑定(bind)。为 global environment .这使它成为全局对象的一个​​属性,因为全局对象是保存全局环境对象环境记录的标识符绑定(bind)的地方。这就是属性不可删除的原因:它不仅仅是一个简单的属性,它还是一个标识符绑定(bind)。

绑定(bind)(变量)是在第一行代码运行之前定义的(参见下面的“当 var 发生时”)。

请注意,在 IE8 及更早版本上,在 window 上创建的属性不可枚举(不会出现在 for..in 语句中)。在 IE9、Chrome、Firefox 和 Opera 中,它是可枚举的。

#1.1 let a = 0;

这将创建一个全局变量,它不是全局对象的属性。这是 ES2015 的新事物。

在规范方面,它为全局环境而不是对象环境记录在声明性环境记录上创建标识符绑定(bind)。全局环境的独特之处在于有一个拆分的环境记录,一个用于全局对象上的所有旧内容(对象环境记录),另一个用于所有新内容( letconst 和创建的函数) by class ) 不在全局对象上。

绑定(bind)是在执行其封闭块中的任何分步代码之前创建的(在这种情况下,在任何全局代码运行之前),但在分步执行到达 let 之前无法以任何方式访问它。声明。一旦执行达到 let声明,该变量是可访问的。 (请参阅下面的“当 letconst 发生时”。)

#1.2 const a = 0;

创建一个全局常量,它不是全局对象的属性。
const就像 let除了您必须提供一个初始值设定项( = value 部分),并且一旦创建常量就不能更改其值。在封面下,它就像 let但是在标识符绑定(bind)上有一个标志说它的值不能改变。使用 const为你做三件事:
  • 如果您尝试分配给常量,则会导致解析时错误。
  • 为其他程序员记录其不变的性质。
  • 让 JavaScript 引擎在它不会改变的基础上进行优化。


  • #2 a = 0;

    这会隐式地在全局对象上创建一个属性。由于它是一个普通属性,您可以将其删除。我建议不要这样做,以后阅读您的代码的任何人都可能不清楚。如果你使用 ES5 的严格模式,这样做(赋值给一个不存在的变量)是一个错误。这是使用严格模式的几个原因之一。

    有趣的是,同样在 IE8 及更早版本上,创建的属性不可枚举(不会出现在 for..in 语句中)。这很奇怪,特别是考虑到下面的 #3。

    #3 window.a = 0;

    这会使用 window 显式地在全局对象上创建一个属性。 global 指的是全局对象(在浏览器上;一些非浏览器环境具有等效的全局变量,例如 NodeJS 上的 global)。由于它是一个普通属性,您可以将其删除。

    此楼盘 可枚举,在 IE8 及更早版本上,以及在我尝试过的所有其他浏览器上。

    #4 this.a = 0;

    与#3 完全一样,除了我们通过 this 引用全局对象而不是全局 window .但是,这在严格模式下不起作用,因为在严格模式下全局代码, this没有对全局对象的引用(取而代之的是值 undefined)。

    删除属性

    “删除”或“移除”是什么意思 a ?正是这样:通过 delete 删除该属性(完全)关键词:
    window.a = 0;
    display("'a' in window? " + ('a' in window)); // displays "true"
    delete window.a;
    display("'a' in window? " + ('a' in window)); // displays "false"
    delete从对象中完全删除属性。你不能用添加到 window 的属性来做到这一点。间接通过 var , delete要么被静默忽略,要么抛出异常(取决于 JavaScript 实现以及您是否处于严格模式)。

    警告 :再次使用 IE8(大概更早,并且 IE9-IE11 处于损坏的“兼容”模式):它不会让您删除 window 的属性反对,即使你应该被允许。更糟糕的是,它会在您尝试时抛出异常(在 IE8 和其他浏览器中为 try this experiment)。所以当从 window 中删除时对象,你必须防御:
    try {
    delete window.prop;
    }
    catch (e) {
    window.prop = undefined;
    }

    这会尝试删除该属性,如果抛出异常,它会执行下一个最好的操作并将该属性设置为 undefined .

    只有适用于 window对象,并且仅(据我所知)适用于 IE8 及更早版本(或 IE9-IE11 处于损坏的“兼容性”模式)。其他浏览器可以删除 window属性,受上述规则的约束。

    var发生

    通过 var 定义的变量语句是在执行上下文中的任何分步代码运行之前创建的,因此该属性早在 var 之前就已存在。声明。

    这可能会令人困惑,所以让我们来看看:
    display("foo in window? " + ('foo' in window)); // displays "true"
    display("window.foo = " + window.foo); // displays "undefined"
    display("bar in window? " + ('bar' in window)); // displays "false"
    display("window.bar = " + window.bar); // displays "undefined"
    var foo = "f";
    bar = "b";
    display("foo in window? " + ('foo' in window)); // displays "true"
    display("window.foo = " + window.foo); // displays "f"
    display("bar in window? " + ('bar' in window)); // displays "true"
    display("window.bar = " + window.bar); // displays "b"

    现场示例:

    display("foo in window? " + ('foo' in window)); // displays "true"
    display("window.foo = " + window.foo); // displays "undefined"
    display("bar in window? " + ('bar' in window)); // displays "false"
    display("window.bar = " + window.bar); // displays "undefined"
    var foo = "f";
    bar = "b";
    display("foo in window? " + ('foo' in window)); // displays "true"
    display("window.foo = " + window.foo); // displays "f"
    display("bar in window? " + ('bar' in window)); // displays "true"
    display("window.bar = " + window.bar); // displays "b"

    function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
    }


    如您所见,符号 foo在第一行之前定义,但符号 bar不是。凡 var foo = "f";声明是,实际上有两件事:定义符号,它发生在第一行代码运行之前;并对该符号进行赋值,这发生在分步流程中该行所在的位置。这被称为“ var 提升”,因为 var foo部分被移动(“提升”)到范围的顶部,但 foo = "f"部分留在原来的位置。 (请参阅我贫血的小博客上的 Poor misunderstood var 。)

    letconst发生
    letconst不同于 var以几种方式。与问题相关的方式是,尽管它们定义的绑定(bind)是在任何分步代码运行之前创建的,但在 let 之前无法访问它。或 const声明达成。

    所以当它运行时:
    display(a);    // undefined
    var a = 0;
    display(a); // 0

    这会引发错误:
    display(a);    // ReferenceError: a is not defined
    let a = 0;
    display(a);

    其他两种方式 letconst不同于 var ,这与问题并不真正相关,是:
  • var始终适用于整个执行上下文(整个全局代码,或它出现的函数中的整个函数代码),但 letconst仅适用于它们出现的块内。即,var具有函数(或全局)范围,但 letconst有块作用域。
  • 重复 var a在相同的上下文中是无害的,但如果你有 let a (或 const a),还有另一个 let aconst avar a是语法错误。

  • 这是一个演示 let 的示例和 const在该块中的任何代码运行之前立即在其块中生效,但在 let 之前无法访问或 const陈述:
    var a = 0;
    console.log(a);
    if (true)
    {
    console.log(a); // ReferenceError: a is not defined
    let a = 1;
    console.log(a);
    }

    注意第二个 console.log失败,而不是访问 a从块外。

    题外话:避免困惑全局对象 ( window )
    window对象变得非常非常困惑的属性。只要有可能,强烈建议不要添加到困惑中。相反,将您的符号包装在一个小包中并最多将一个符号导出到 window目的。 (我经常不将任何符号导出到 window 对象。)您可以使用一个函数来包含您的所有代码以包含您的符号,如果您愿意,该函数可以是匿名的:
    (function() {
    var a = 0; // `a` is NOT a property of `window` now

    function foo() {
    alert(a); // Alerts "0", because `foo` can access `a`
    }
    })();

    在那个例子中,我们定义了一个函数并让它立即执行(最后是 ())。

    以这种方式使用的函数通常称为作用域函数。作用域函数中定义的函数可以访问作用域函数中定义的变量,因为它们是对数据的闭包(请参阅: Closures are not complicated 在我的贫血小博客上)。

    关于javascript - Javascript中变量声明语法的区别(包括全局变量)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4862193/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com