Yes, there are a couple of differences, though in practical terms they're not usually big ones.(是的,有一些差异,尽管实际上它们通常并不大。)
There's a fourth way, and as of ES2015 (ES6) there's two more.(还有第四种方法,从ES2015(ES6)开始,还有另外两种方法。) I've added the fourth way at the end, but inserted the ES2015 ways after #1 (you'll see why), so we have:(我在末尾添加了第四种方式,但是在#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
Those statements explained(这些陈述解释了)
#1 var a = 0;
(#1 var a = 0;
)
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).(这将创建一个全局变量,该变量也是全局对象的属性,我们可以在浏览器中以window
访问该变量(或通过this
window
在非严格代码中通过全局范围访问)。) Unlike some other properties, the property cannot be removed via delete
.(与某些其他属性不同,该属性无法通过delete
。)
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.(这就是为什么该属性不可删除的原因:它不仅是一个简单的属性,还是一个标识符绑定。)
The binding (variable) is defined before the first line of code runs (see "When var
happens" below).(绑定(变量)是在代码的第一行运行之前定义的(请参见下面的“何时发生var
”)。)
Note that on IE8 and earlier, the property created on window
is not enumerable (doesn't show up in for..in
statements).(请注意,在IE8和更早版本上,在window
上创建的属性不可枚举 (不会显示在for..in
语句中)。) In IE9, Chrome, Firefox, and Opera, it's enumerable.(在IE9,Chrome,Firefox和Opera中,它是枚举的。)
#1.1 let a = 0;
(#1.1 let a = 0;
)
This creates a global variable which is not a property of the global object.(这将创建一个全局变量,该变量不是全局对象的属性。) This is a new thing as of ES2015.(从ES2015开始这是新事物。)
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
, const
和由class
创建的函数),不要继续使用全局对象。)
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.(绑定是在执行其封闭块中的任何分步代码之前创建的 (在这种情况下,在任何全局代码运行之前),但是在分步执行到达let
语句之前,它无法以任何方式访问 。) Once execution reaches the let
statement, the variable is accessible.(一旦执行到达let
语句,就可以访问该变量。) (See "When let
and const
happen" below.)((请参见下面的“当let
和const
发生时”。))
#1.2 const a = 0;
(#1.2 const a = 0;
)
Creates a global constant, which is not a property of the global object.(创建一个全局常量,它不是全局对象的属性。)
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.(const
就像let
一样,除了必须提供一个初始化程序( = value
部分),并且一旦创建常量就无法更改其值。) Under the covers, it's exactly like let
but with a flag on the identifier binding saying its value cannot be changed.(在幕后,它就像let
一样,但是在标识符绑定上带有一个标志,表明其值不能更改。) Using const
does three things for you:(使用const
可以为您做三件事:)
Makes it a parse-time error if you try to assign to the constant.(如果您尝试分配给常量,则使其成为解析时错误。)
Documents its unchanging nature for other programmers.(记录其对于其他程序员的不变性。)
Lets the JavaScript engine optimize on the basis that it won't change.(让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.(我建议您不要这样做,以后再阅读您的代码的人可能会不清楚。) If you use ES5's strict mode, doing this (assigning to a non-existent variable) is an error.(如果您使用ES5的严格模式,则执行此操作(将其分配给不存在的变量)是错误的。) It's one of several reasons to use strict mode.(使用严格模式是多种原因之一。)
And interestingly, again on IE8 and earlier, the property created not enumerable (doesn't show up in for..in
statements).(有趣的是,再次在IE8和更早版本上,创建的属性不可枚举 (不会出现在for..in
语句中)。) That's odd, particularly given #3 below.(这很奇怪,特别是在下面的#3中。)
#3 window.a = 0;
(#3 window.a = 0;
)
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).(这创建全局对象上的属性明确,使用window
,指的全局对象全局(在浏览器上;一些非浏览器环境具有等同的全局变量,诸如global
上的NodeJS)。) As it's a normal property, you can delete it.(由于它是普通属性,因此可以将其删除。)
This property is enumerable, on IE8 and earlier, and on every other browser I've tried.(在IE8和更早版本以及我尝试过的所有其他浏览器上,此属性都是可枚举的。)
#4 this.a = 0;
(#4 this.a = 0;
)
Exactly like #3, except we're referencing the global object through this
instead of the global window
.(就像#3一样,除了我们通过this
而不是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).(这在严格模式是行不通的,但是,因为在严格模式全局代码, this
不具有全局对象(它的价值的参考undefined
代替)。)
Deleting properties(删除属性)
What do I mean by "deleting" or "removing" a
?(“删除”或“删除” a
是什么意思?) Exactly that: Removing the property (entirely) via the delete
keyword:(正是这样:通过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
completely removes a property from an object.(delete
完全删除对象的属性。) 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).(通过var
间接将属性添加到window
,您将无法做到这一点, delete
会被静默忽略或引发异常(取决于JavaScript实现以及您是否处于严格模式)。)
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.(警告 :IE8再次出现(可能是更早的版本,而IE9-IE11处于损坏的“兼容性”模式):即使允许,也不允许您删除window
对象的属性。) Worse, it throws an exception when you try ( try this experiment in IE8 and in other browsers).(更糟糕的是,尝试时会引发异常 (在IE8和其他浏览器中尝试此实验 )。) So when deleting from the window
object, you have to be defensive:(因此,从window
对象中删除时,您必须采取防御措施:)
try {
delete window.prop;
}
catch (e) {
window.prop = 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
.(尝试删除该属性,如果抛出异常,它将做第二件事,并将属性设置为undefined
。)
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).(这仅适用于window
对象,并且仅(据我所知)适用于IE8和更早的版本(或处于“兼容”模式的IE9-IE11)。) Other browsers are fine with deleting window
properties, subject to the rules above.(其他浏览器可以删除window
属性,但要遵守上述规则。)
<h与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…