深入理解ES6(1)

从var到let和const

var变量提升

在函数作用域和全局作用域中,var声明的变量都被当成在作用域顶部声明的变量。

块级声明

  • 函数内部
  • 块中({ }之间)

let声明

  • 作用:把作用域限制在代码块中。

禁止重声明

作用域中已存在某个标识符(var、let、const),再let声明就会报错。

const声明

const声明变量

定义后不可更改,通过const声明的变量必须进行初始化。

const声明对象

不允许修改对象,但可以修改对象的属性值。

临时死区TDZ

js引擎在扫描代码发现变量声明时,要么提升至作用域顶部(遇到var声明),要么将声明放到TDZ中。访问TDZ中的变量会触发运行时错误。执行过变量声明语句后,变量才会从TDZ中移出,然后才能正常访问。

循环中的块作用域绑定

1
2
3
4
for ( var i = 0; i< 10; i++ ) {
console.log(i)
}
console.log(i)

在循环结束后仍能访问 i = 10

1
2
3
4
for ( let i = 0; i< 10; i++ ) {
console.log(i)
}
console.log(i)

循环结束后,i无法访问,跑出错误

循环中的函数

预期输出0~9

1
2
3
4
5
6
7
8
9
10
11
var funcs = []

for ( var i = 0 ; i < 10 ; i++ ) {
funcs.push(function(){
console.log(i)
})
}

funcs.forEach(function(func){
func() //输出10次10
})

因为共享变量i

调用函数表达式IIFE

1
2
3
4
5
6
7
8
9
10
11
12
13
var funcs = []

for ( var i = 0 ; i < 10 ; i++ ) {
funcs.push(function(value){
return function(){
console.log(value)
}
}(i)))
}

funcs.forEach(function(func){
func() //输出0~9
})

IIFE为每个变量i都创建了一个副本并存储为变量value,这个变量的值就是相应迭代创建的函数所用的值。
闭包 闭包概念参考

循环中的let声明

每次迭代循环都会创建一个新变量,并以之前迭代中同名变量的值将其初始化。

1
2
3
4
5
6
7
8
9
10
var funcs = []
for (let i = 0; i < 10 ; i++) {
funcs.push(function(){
console.log(i)
})
}

funcs.forEach(function(func) {
func() //输出0~9
})

for-in与for一样

循环中的const声明

for循环中,试图修改i,但i是常量,会报错。在for-in和for-of中使用和let一致,每次迭代不会修改已有绑定,会创建一个新绑定,不会报错。

for、forEach 、for in、for of 循环的区别

全局块作用域绑定

var会创建一个新的全局变量作为全局对象(window对象)的属性。var可能会无意覆盖一个已存在的全局属性。
用let和const不会覆盖全局变量,只能遮盖。

JS中通过var定义全局变量与在window对象上直接定义属性的区别