这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
let 与 const
ES5 中声明变量命令只有两种 var 和 function
ES6 中除了 var、function,新增了 let、const、class、import,一共六种
-
let 是 ES6 新增的声明命令,功能类似于 ES5 中的 var 关键字
-
let 声明的变量尽在所在代码块内有效
{ let a = 0 var b = 1 } console.log(b) // 1 console.log(a) // ReferenceError // 这表明 let 声明的变量只在它所在的代码块有效
let 命令很适合在 for 循环中使用
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10 // var 声明的 i,全局有效,每一次循环,新的 i 值都会覆盖旧值,导致最后输出的是最后一轮的 i 的值 var b = []; for (let j = 0; j < 10; j++) { b[j] = function () { console.log(j); }; } b[6](); // 6 // 变量 j 使用 let 声明,当前的 j 只在本轮循环有效,每一次循环的 j 其实都是一个新的变量,所以最后输出的是 6
-
let 命令不允许重复声明
// SyntaxError function test1() { let a = 10 var a = 1 } // SyntaxErrot function test2() { let a = 10 let a = 1 } // SyntaxError function test3(a) { let a = 1 }
-
暂行性死区
// ReferenceError console.log(a) let a = 0
同一代码块中,使用 let 命令声明的变量,不能在声明之前使用,会报引用错误
代码块中,变量声明前,该变量不可用,语法上称之为暂行性死区(temporal dead zone,简称 TDZ)
-
const 和 let 作用和特性类似,只在当前代码块有效,不能重复声明
const 声明时必须赋初值,且不可改变其值
const a = 1 a = 2 // TypeError const b // SyntaxError
-
let、const 变量提升
下面代码 let 重复声明会报语法错误,但在报错之前 console.log 不能正常输出
说明存在变量提升
let a = 1 console.log(a) let a = 2 // SyntaxError
但是由于暂行性死区的存在,我们无法在声明之前使用变量
console.log(a) // undefined console.log(b) // ReferenceError var a = 2 let b = 2
注:变量的定义分为创建 -> 初始化为 undefined -> 赋值三个阶段
let 的创建过程被提升,但是初始化没有提升
var 的创建和初始化被提升
function 的创建、初始化和赋值都被提升
块级作用域
-
ES5 中只有全局作用域和函数作用域
// 全局作用域 var a = 0 function test() { // 函数作用域 var a = 1 }
存在的问题
var a = 0 function test() { console.log(a) if(false) { var a = 1 } } test() // undefined
函数作用域下中 if 中 var a 命令变量提升,导致 a 为 undefined
-
ES6 中规定 {} 内部为一个独立的块级作用域
外层代码块不受内层代码块的影响
外层作用域无法读取内层作用域的变量
内层作用域可以定义外层作用域的同名变量
{{ let a = 0 { let a = 1 { console.log(a) // 报错 } } }}
-
块级作用域的出现让广泛运用的的立即执行函数不再必要
// IIFE 写法 (function () { var tmp = ...; ... }()); // 块级作用域写法 { let tmp = ...; ... }
函数声明
-
ES5 规定函数只能在全局作用域和函数作用域中声明
// 情况一 if (true) { function fn() {} } // 情况二 try { function fn() {} } catch(e) { }
以上为非法的声明,但是为了兼容旧代码,浏览器没有遵守此规定,可以运行,不会报错,但是严格模式下会报错
// ES5 严格模式 'use strict'; if (true) { function fn() {} } // 报错
-
ES6 引入块级作用域,明确允许可以在块级作用域声明函数
// ES6 严格模式 'use strict'; if (true) { function fn() {} } // 不报错
-
ES6 规定块级作用域中的函数声明,无法在作用域外引用
function fn() { console.log('outside') } (function () { if (false) { // 重复声明一次函数 function fn() { console.log('inside') } } fn() }())
在 ES5 中会打印出 inside,因为 if 块里面的 fn 被提升到自执行函数头部
在 ES6 中则打印出 outside,因为在 if 块内声明的 fn,作用域外无法访问,只能执行外部声明的 fn
由于行为差异较大,ES6 规定浏览器可以不遵守该项,有自己的行为方式
- 允许在块级作用域内声明函数
- 函数声明类似于 var,即提升到全局作用域或函数作用域的头部
- 同时,函数声明会提升到所在的块级作用域的头部
上面示例代码在 chrome 环境中可能会报错,因为实际运行的代码如下
function fn() { console.log('outside') } (function () { var fn = undefined if (false) { function fn() { console.log('inside') } } fn() }()) // Uncaught TypeError: fn is not a function