這是我參與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
複製代碼