这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战javascript
ES5 中声明变量命令只有两种 var 和 functionjava
ES6 中除了 var、function,新增了 let、const、class、import,一共六种chrome
let 是 ES6 新增的声明命令,功能相似于 ES5 中的 var 关键字浏览器
let 声明的变量尽在所在代码块内有效markdown
{
let a = 0
var b = 1
}
console.log(b) // 1
console.log(a) // ReferenceError
// 这代表 let 声明的变量只在它所在的代码块有效
复制代码
let 命令很适合在 for 循环中使用ide
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
}
复制代码
暂行性死区post
// ReferenceError
console.log(a)
let a = 0
复制代码
同一代码块中,使用 let 命令声明的变量,不能在声明以前使用,会报引用错误ui
代码块中,变量声明前,该变量不可用,语法上称之为暂行性死区(temporal dead zone,简称 TDZ)spa
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
复制代码