const
The const declaration creates block-scoped constants, much like variables declared using the let keyword. The value of a constant can’t be changed through reassignment (i.e. by using the assignment operator), and it can’t be redeclared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed
常量是块级范围的,非常类似用 let 语句定义的变量。但常量的值是无法(通过重新赋值)改变的,也不能被重新声明。文档描述
实践:
//eg1:
const a = 12
if (a) {
const a = 10
console.log(a)
}
console.log(a)
//console:
>10
>12
//eg2:
const a = new Object({name: 'jack'})
const b = new Object({name: 'jack'})
a.name = 'peters'
delete b.name
console.log(a,b)
//console:
> [object Object] { name: "peters" },[object Object] { ... }
//eg3:
/*
数组shift方法用于删除数组第一个元素
数组pop方法用于删除数组最后一个元素
*/
const a = new Array(1)
const b = new Array(1)
a[0] = 'peters'
b.shift() //[] 结果和pop()一样
console.log(a,b)
//console:
>["peters"],[]
key points:
- block-scoped (块作用域)
- value can’t be changed, and it can’t be redeclared (常量的值不可被更改,常量也不能重新被声明)
- 在声明的同一语句中必须指定它的值 (因为声明的常量值是不可更改的)
- However, if a constant is an object or array its properties or items can be updated or removed (const定义的常量是对象或数组时,它们的属性或者items(数组中的一项或某项)能被赋值更新或移除(删除))
var
The var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.
var 语句 用于声明一个函数范围或全局范围的变量,并可将其初始化为一个值(可选)文档描述
描述
var declarations, wherever they occur, are processed before any code is executed. This is called hoisting and is discussed further below.
The scope of a variable declared with var is its current execution context and closures thereof (which is either the enclosing function and functions declared within it) , or, for variables declared outside any function, global. Duplicate variable declarations using var will not trigger an error, even in strict mode, and the variable will not lose its value, unless another assignment is performed.
无论在何处声明变量,都会在执行任何代码之前进行处理。这被称为变量提升
用 var 声明的变量的作用域是它当前的执行上下文及其闭包(嵌套函数),或者对于声明在任何函数外的变量来说是全局。使用 var 重复声明 JavaScript 变量并不会抛出错误(即使在严格模式 (strict mode) 下),同时,变量也不会丢失其值,直到调用其它的赋值操作。
hoisting (变量提升)
Because var declarations are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it’s declared. This behavior is called hoisting, as it appears that the variable declaration is moved to the top of the function or global code.
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。
实践:
//eg1:
var a = 1
if (a == 1){
var a = 2
console.log(a)
}
console.log(a)
//console:
>2
>2
//eg2:
function foo() {
var x = 1;
function bar() {
var y = 2;
console.log(x); // 1 (函数 `bar` 包含了 `x`)
console.log(y); // 2 (`y` 在作用域内)
}
bar();
console.log(x); // 1 (`x` 在作用域内)
console.log(y); // 在严格模式(strict mode)下将抛出 ReferenceError,`y` 仅在 `bar` 函数的作用域内
}
foo();
//console:
>1
>2
>1
> "Uncaught ReferenceError: y is not defined"
//eg3:
var a, b
(
function() {
console.log(a)
console.log(b)
var a = (b = 3)
console.log(a)
console.log(b)
}
)()
console.log(a)
console.log(b)
//console:
>undefined
>undefined
>3
>3
>undefined
>3
拓展释义
IIFE(立即调用函数表达式)
这是一个被称为 自执行匿名函数 的设计模式,主要包含两部分。
- 第一部分是包围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。
- 第二部分再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。
key points
- 函数范围或全局范围的变量 ==> 作用域是它当前的执行上下文及其闭包(嵌套函数)
- 并可将其初始化为一个值(可选),不初始化则为undefined
- 变量提升 ==> 在代码中的任意位置声明变量总是等效于在代码开头声明
let
The let declaration declares a block-scoped local variable, optionally initializing it to a value.
let 语句声明一个块级作用域的局部变量,并可以初始化为一个值(可选)。文档描述
描述
let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope. The other difference between var and let is that the latter can only be accessed after its declaration is reached (see temporal dead zone). For this reason, let declarations are commonly regarded as non-hoisted.
Just like const the let does not create properties of the window object when declared globally (in the top-most scope).
An explanation of why the name “let” was chosen can be found here.
Many issues with let variables can be avoided by declaring them at the top of the scope in which they are used (doing so may impact readability).
Unlike var, let begins declarations, not statements. That means you cannot use a lone let declaration as the body of a block (which makes sense, since there’s no way to access the variable).
let 允许你声明一个作用域被限制在块作用域中的变量、语句或者表达式。与 var 关键字不同的是,var 声明的变量作用域是全局或者整个函数块的。 var 和 let 的另一个重要区别,let 声明的变量不会在作用域中被提升,它是在编译时才初始化(参考下面的暂时性死区)。
就像 const 一样,let 不会在全局声明时(在最顶层的作用域)创建 window 对象的属性。
可以从这里了解我们为什么使用 let。通过在使用 let 变量的作用域顶部声明它们,可以避免很多问题,但这样做可能会影响可读性。
与 var 不同的是,let 只是开始声明,而非一个完整的表达式。这意味着你不能将单独的 let 声明作为一个代码块的主体(这是有道理的,因为声明的变量无法被访问)。
实践:
Scoping rules
let 声明的变量作用域只在其声明的块或子块内部,这一点,与 var 相似。二者之间最主要的区别在于 var 声明的变量的作用域是整个封闭函数。
//eg1:
function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
function constTest() {
const a = 1;
{
const a = 2
console.log(a)//same as the let declaration
}
console.log(a)//1
}
varTest()
letTest()
constTest()
//console:
>2
>2
>2
>1
>2
>1
At the top level of programs and functions, let, unlike var, does not create a property on the global object.
在全局作用域中,let 和 var 不一样,它不会在全局对象上创建属性
var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined
在同一个函数或块作用域中重复声明同一个变量会抛出 SyntaxError
if (x) {
let foo;
let foo; // SyntaxError thrown.
}
在 switch 语句中也会触发这个错误,因为它是同一个块作用域。
let x = 1;
switch(x) {
case 0:
let foo;
break;
case 1:
let foo; // SyntaxError for redeclaration.
break;
}
一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境,就不会产生上诉重复声明的错误。
let x = 1;
switch(x) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}
Temporal dead zone,TDZ (暂时性死区)
从一个代码块的开始直到代码执行到声明变量的行之前,let 或 const 声明的变量都处于“暂时性死区”中
当变量处于暂时性死区之中时,其尚未被初始化,尝试访问变量将抛出 ReferenceError。当代码执行到声明变量所在的行时,变量被初始化为一个值。如果声明中未指定初始值,则变量将被初始化为 undefined。
与 var 声明的变量不同,如果在声明前访问了变量,变量将会返回 undefined。以下代码演示了在使用 let 和 var 声明变量的行之前访问变量的不同结果。
{ // TDZ starts at beginning of scope
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2; // End of TDZ (for foo)
}
暂时性死区(TDZ),是let,const声明的变量从一个代码块(块作用域)开始执行到声明之前所处在的状态。从 var 关键字的方向来看,TDZ的产生是因为语句执行的先后顺序产生的,var存在变量提升,即无论var定义到何处,都会将定义语句提升到var作用域(函数块或执行上下文)开始之前执行(变量提升),所以从代码块开始执行到let,const语句声明之前,声明的变量都处于暂时性死区
文档描述:The term “temporal” is used because the zone depends on the order of execution (time) rather than the order in which the code is written (position). For example, the code below works because, even though the function that uses the let variable appears before the variable is declared, the function is called outside the TDZ.
使用术语“temporal”是因为区域取决于执行顺序(时间),而不是编写代码的顺序(位置)。例如,下面的代码会生效,是因为即使使用 let 变量的函数出现在变量声明之前,但函数的执行是在暂时性死区的外面。
{
// TDZ starts at beginning of scope. TDZ从作用域(块作用域)最开始是开始
const func = () => console.log(letVar); // OK
// Within the TDZ letVar access throws `ReferenceError`
let letVar = 3; // End of TDZ (for letVar). letVar TDZ结束
func(); // Called outside TDZ!
}
由于外部变量 foo 有值,因此会执行 if 语句块,但是由于词法作用域,该值在块内不可用:if 块内的标识符 foo 是 let foo。表达式 (foo + 55) 会抛出 ReferenceError 异常,是因为 let foo 还没完成初始化,它仍然在暂时性死区里。
function test() {
var foo = 33;
if(foo) {
let fool = (foo + 55); // ReferenceError
console.log(fool,foo)
// let foo = 'a'
}
}
test();
其他情况
用在块级作用域中,let 将变量的作用域限制在块内,而 var 声明的变量的作用域是在函数内。
var a = 1;
var b = 2;
if (a === 1) {
var a = 11; // the scope is global
let b = 22; // the scope is inside the if-block
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
然而,var 与 let 合并的声明方式会抛出 SyntaxError 错误,因为 var 会将变量提升至块的顶部,这会导致隐式地重复声明变量。
let x = 1;
{
var x = 2; // SyntaxError for re-declaration
}
key Points
- 块级作用域的局部变量
- Just like const the let does not create properties of the window object when declared globally (in the top-most scope).
tidy
let | var | const | |
---|---|---|---|
作用域 | 块级作用域 | 执行上下文或函数范围(var 语句 用于声明一个函数范围或全局范围的变量) | 全局或本地声明的块 |
被声明的变量值特点 | 可更改值的变量 | 可更改值的变量 | 常量且不可更改(初始化必须指定值) |
变量声明语句所在的作用域内重复声明同一变/常量 | 不可重复声明 | 可以重复声明 | 不可重复声明 |
参考资料:MDN
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net