Javascript中的变量声明语法之间的区别(包括全局变量)? [英] Difference between variable declaration syntaxes in Javascript (including global variables)?

查看:107
本文介绍了Javascript中的变量声明语法之间的区别(包括全局变量)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

声明变量之间是否有任何区别:

Is there any difference between declaring a variable:

var a=0; //1

......这样:

a=0; //2

...或:

window.a=0; //3

在全球范围内?

推荐答案

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

Yes, there are a couple of differences, though in practical terms they're not usually big ones.

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

There's a fourth way, and as of ES2015 (ES6) there's two more. I've added the fourth way at the end, but inserted the ES2015 ways after #1 (you'll see why), so we have:

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;

Those statements explained

#1 var a = 0;

这会创建一个全局变量 全局对象的属性 ,我们在浏览器上访问窗口(或通过全局范围,非 - 严格的代码)。与其他一些属性不同,该属性不能通过 delete 删除。

This creates a global variable which is also a property of the global object, which we access as window on browsers (or via this a global scope, in non-strict code). Unlike some other properties, the property cannot be removed via delete.

在规范方面,它会创建一个 对象上的标识符绑定 href =http://www.ecma-international.org/ecma-262/6.0/index.html#sec-global-environment-records的>环境记录 =noreferrer> 全球环境 。这使得它成为全局对象的属性,因为全局对象是保存全局环境的对象环境记录的标识符绑定的地方。这就是属性不可删除的原因:它不仅仅是一个简单的属性,它是一个标识符绑定。

In specification terms, it creates an identifier binding on the object Environment Record for the global environment. That makes it a property of the global object because the global object is where identifier bindings for the global environment's object Environment Record are held. This is why the property is non-deletable: It's not just a simple property, it's an identifier binding.

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

The binding (variable) is defined before the first line of code runs (see "When var happens" below).

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

Note that on IE8 and earlier, the property created on window is not enumerable (doesn't show up in for..in statements). In IE9, Chrome, Firefox, and Opera, it's enumerable.

#1.1 设a = 0;

#1.1 let a = 0;

这会创建一个全局变量,属性全球对象。这是ES2015的新功能。

This creates a global variable which is not a property of the global object. This is a new thing as of ES2015.

在规范术语中,它为全局环境的声明性环境记录创建了一个标识符绑定而不是对象环境记录。全局环境在分割环境记录方面是独一无二的,一个用于全局对象上的所有旧东西(对象环境记录),另一个用于所有新东西(让, const ,以及由 class 创建的函数在全局对象上。

In specification terms, it creates an identifier binding on the declarative Environment Record for the global environment rather than the object Environment Record. The global environment is unique in having a split Environment Record, one for all the old stuff that goes on the global object (the object Environment Record) and another for all the new stuff (let, const, and the functions created by class) that don't go on the global object.

在执行其封闭块中的任何分步代码之前,绑定是创建(在这种情况下,在任何全局代码运行之前),但在逐步执行到达 let 语句之前,它不会以任何方式可访问。一旦执行到达 let 语句,该变量就可以访问。 (参见下面的当 const 发生时。)

The binding is created before any step-by-step code in its enclosing block is executed (in this case, before any global code runs), but it's not accessible in any way until the step-by-step execution reaches the let statement. Once execution reaches the let statement, the variable is accessible. (See "When let and const happen" below.)

#1.2 const a = 0;

#1.2 const a = 0;

创建一个全局常量,它不是全局对象的属性。

Creates a global constant, which is not a property of the global object.

const 就像 let 一样,除了你必须提供一个初始化器( = value 部分),你不能改变它的值一旦它被创造出来的常数。在封面下,它与完全相同,但标识符绑定上有一个标志,表示其值无法更改。使用 const 为您做三件事:

const is exactly like let except that you must provide an initializer (the = value part), and you cannot change the value of the constant once it's created. Under the covers, it's exactly like let but with a flag on the identifier binding saying its value cannot be changed. Using const does three things for you:


  1. 使其成为解析时错误如果你试图分配给常量。

  2. 记录其对其他程序员不变的性质。

  3. 让JavaScript引擎在赢得的基础上进行优化不要改变。






#2 a = 0;


#2 a = 0;

这会在全局对象上隐式创建一个属性。由于它是普通属性,您可以删除它。我建议这样做,以后读取你的代码的任何人都不清楚。

This creates a property on the global object implicitly. As it's a normal property, you can delete it. I'd recommend not doing this, it can be unclear to anyone reading your code later.

有趣的是,再次在IE8及更早版本中,创建的属性不是可枚举的(不会显示在 for..in 语句中)。这很奇怪,特别是下面的#3。

And interestingly, again on IE8 and earlier, the property created not enumerable (doesn't show up in for..in statements). That's odd, particularly given #3 below.

#3 window.a = 0;

#3 window.a = 0;

使用窗口显式创建全局对象的属性 global引用全局对象(在浏览器上;某些非浏览器环境具有等效的全局变量,例如NodeJS上的 global )。因为这是一个普通的属性,你可以删除它。

This creates a property on the global object explicitly, using the window global that refers to the global object (on browsers; some non-browser environments have an equivalent global variable, such as global on NodeJS). As it's a normal property, you can delete it.

这个属性 可枚举,在IE8及更早版本,以及其他所有浏览器上我都可以我试过了。

This property is enumerable, on IE8 and earlier, and on every other browser I've tried.

#4 this.a = 0;

#4 this.a = 0;

与#3完全相同,只是我们通过引用全局对象而不是全局窗口。但是,这在严格模式下不起作用,因为在严格模式全局代码中,没有对全局对象的引用(它的值 undefined 代替)。

Exactly like #3, except we're referencing the global object through this instead of the global window. This won't work in strict mode, though, because in strict mode global code, this doesn't have a reference to the global object (it has the value undefined instead).

删除或删除 a 是什么意思?正是如此:通过删除属性(完全)删除关键字:

What do I mean by "deleting" or "removing" a? Exactly that: Removing the property (entirely) via the delete keyword:

window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"

删除完全从对象中删除属性。通过 var 间接添加到 window 的属性, delete 要么被静默忽略,要么抛出异常(取决于JavaScript实现以及你是否处于严格模式)。

delete completely removes a property from an object. You can't do that with properties added to window indirectly via var, the delete is either silently ignored or throws an exception (depending on the JavaScript implementation and whether you're in strict mode).

警告:IE8再次(大概早些时候,IE9-IE11处于破坏的兼容性模式):它不会让你删除窗口对象的属性,即使你应该被允许。更糟糕的是,当您尝试(在IE8和其他中尝试此实验时,它会抛出异常浏览器)。因此,当从窗口对象中删除时,您必须具有防御性:

Warning: IE8 again (and presumably earlier, and IE9-IE11 in the broken "compatibility" mode): It won't let you delete properties of the window object, even when you should be allowed to. Worse, it throws an exception when you try (try this experiment in IE8 and in other browsers). So when deleting from the window object, you have to be defensive:

try {
    delete window.prop;
}
catch (e) {
    window.prop = undefined;
}

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

That tries to delete the property, and if an exception is thrown it does the next best thing and sets the property to undefined.

适用于窗口对象,只有(据我所知)到IE8及更早版本(或者在破坏的兼容性模式下为IE9-IE11)。其他浏览器可以删除 window 属性,但需遵守上述规则。

This only applies to the window object, and only (as far as I know) to IE8 and earlier (or IE9-IE11 in the broken "compatibility" mode). Other browsers are fine with deleting window properties, subject to the rules above.

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

The variables defined via the var statement are created before any step-by-step code in the execution context is run, and so the property exists well before the var statement.

这可能令人困惑,所以我们来看看:

This can be confusing, so let's take a look:

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 hoisting,因为 var foo 部分被移动(悬挂)到顶部范围,但 foo =f部分保留在其原始位置。 (参见 可怜的误解 var 在我贫穷的小博客上。)

As you can see, the symbol foo is defined before the first line, but the symbol bar isn't. Where the var foo = "f"; statement is, there are really two things: defining the symbol, which happens before the first line of code is run; and doing an assignment to that symbol, which happens where the line is in the step-by-step flow. This is known as "var hoisting" because the var foo part is moved ("hoisted") to the top of the scope, but the foo = "f" part is left in its original location. (See Poor misunderstood var on my anemic little blog.)

const 在几个方面与 var 不同。与问题相关的方式是,尽管它们定义的绑定是在任何逐步执行代码之前创建的,但在 let 可访问 c>或 const 语句已达到。

let and const are different from var in a couple of ways. The way that's relevant to the question is that although the binding they define is created before any step-by-step code runs, it's not accessible until the let or const statement is reached.

所以当这个运行时:

display(a);    // undefined
var a = 0;
display(a);    // 0

这会抛出错误:

display(a);    // ReferenceError: a is not defined
let a = 0;
display(a);

另外两种 const var 不同,与问题无关,是:

The other two ways that let and const differ from var, which aren't really relevant to the question, are:


  1. var 始终适用于整个执行上下文(遍及全局代码,或整个函数中的函数代码)它出现的地方),但是 const 仅在它们出现的中应用。也就是说, var 具有函数(或全局)范围,但是 const 具有块范围。

  1. var always applies to the entire execution context (throughout global code, or throughout function code in the function where it appears), but let and const apply only within the block where they appear. That is, var has function (or global) scope, but let and const have block scope.

在同一上下文中重复 var a 是无害的,但是如果你有让一个(或者 const a ),还有一个让一个 const a var a 是语法错误。

Repeating var a in the same context is harmless, but if you have let a (or const a), having another let a or a const a or a var a is a syntax error.

这是一个示例,证明 const 在该块中的任何代码运行之前立即在其块中生效,但在 let const 声明:

Here's an example demonstrating that let and const take effect immediately in their block before any code within that block runs, but aren't accessible until the let or const statement:

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

Note that the second console.log fails, instead of accessing the a from outside the block.

window 对象变得非常非常混乱。只要有可能,强烈建议不要添加到混乱中。相反,将符号包装在一个小包中,然后将 most 一个符号导出到窗口对象。 (我经常不将任何符号导出到窗口对象。)您可以使用函数来包含所有代码以便包含您的符号,如果您愿意,该函数可以是匿名的:

The window object gets very, very cluttered with properties. Whenever possible, strongly recommend not adding to the mess. Instead, wrap up your symbols in a little package and export at most one symbol to the window object. (I frequently don't export any symbols to the window object.) You can use a function to contain all of your code in order to contain your symbols, and that function can be anonymous if you like:

(function() {
    var a = 0; // `a` is NOT a property of `window` now

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

在该示例中,我们定义一个函数并立即执行(()最后)。

In that example, we define a function and have it executed right away (the () at the end).

以这种方式使用的函数通常称为作用域函数。在作用域函数中定义的函数可以访问作用域函数中定义的变量,因为它们是闭包而不是该数据(参见: 我的贫血小博客上的闭包并不复杂

A function used in this way is frequently called a scoping function. Functions defined within the scoping function can access variables defined in the scoping function because they're closures over that data (see: Closures are not complicated on my anemic little blog).

这篇关于Javascript中的变量声明语法之间的区别(包括全局变量)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆