在 ES6 之前,JS 中沒有常量聲明體式格局,有的僅僅是一種定名上的商定。
var PI = 3.14;
PI = 4;
console.log(PI); // 4
我們用大寫變量名來標識這是一個常量,但這類商定並不能保證常量的不可變,在順序的實行過程當中,照舊有能夠轉變該常量的值。
而在 ES6 中,給出了聲明一個常量的要領:
const PI = 3.14;
PI = 4; // Uncaught TypeError: Assignment to constant variable.
經由過程 const 聲明的常量在賦值以後不能再次舉行賦值,不然會報錯。
在運用 ES6 的順序中,我們首倡對變量聲明時採納 const 來替代 var。在確切須要轉變變量的值的時刻運用 let。如許就能夠最大程度上躲避變量的不測變化來使順序發作非常的能夠性。
有句陳詞濫調的話,JS 中一切皆對象。JS 中的數據範例有兩類,一類是按值通報,另一類使按援用通報。
關於字符串数字等基礎範例,變量保留的指向該值現實數據的內存地址。而關於對象,變量保留的是指向該對象的一個內存援用。
所以,現實上 const 綁定的不可變常量關於對象而言,是其指向的對象的內存地址綁定不可變,而非指向對象的屬性不可轉變。
const person = {
name: 'John',
age: 20
};
person.name = 'Tom';
console.log(person.name); // Tom
person = {} // Uncaught TypeError
除了對屢次賦值的毛病提醒外,運用 let 和 const 以替代帶來的優點另有完成了塊級作用域。
在任何一本 es6 之前的 js 書中,變量部份險些都邑通知我們,js 中的變量沒有塊級作用域。作用域是函數作用域。
順着作用域鏈,在非函數內聲明的變量會存在於全局作用域中,在瀏覽器環境中,他會變成 window 對象的一個屬性。
var PI = 3.14
console.log(window.PI) // 3.14
為了防止作用域的污染,在 ES5 中須要運用一個馬上實行函數來確保變量的作用域局限。
(function () {
var PI = 3.14;
console.log(PI); // 3.14
})();
console.log(PI); //undefined
此時形成了一個閉包。
一個典範題目,輪迴綁定事宜:
var buttons = document.querySelectorAll('.button');
for (var i = 0; i < buttons.length; ++i) {
buttons[i].addEnentListener('click', function(evt) {
console.log(i)
}, false)
}
在頁面中,為三個按鈕綁定 click 事宜,輸出響應按鈕的數組下標索引。
效果我們能夠看到,三個按鈕綁定的 i 值均為 3。也就是說,在上述輪迴中,按鈕綁定的值為 i 末了一次自增的值。
為了將綁定的 i 值限定在每次輪迴內,也就是須要在 for 輪迴內形成塊級作用域。
在 ES5 之前,能夠如許改寫:
var buttons = document.querySelectorAll('.button');
for (var i = 0; i < buttons.length; ++i) {
(function (i) {
buttons[i].addEventListener('click', function(evt) {
console.log(i)
}, false)
})(i)
}
應用閉包,我們保留來每次輪迴三次天生三個作用域,三個作用域的值互不影響。
閉包使得變量的生命周期得以連續。
而關於 ES6,有了 let,就能夠直接用起來了。
const buttons = document.querySelectorAll('.button');
for (let i = 0; i < buttons.length; ++i) {
buttons[i].addEventListener('click', function(evt) {
console.log(i)
}, false)
}
前面我們提到過,運用 var 聲明的變量在全局作用域中會成為全局對象的一個屬性:
window.PI = 3.14;
var PI = 4;
console.log(PI); // 4
console.log(window.PI); // 4
而 const 和 let 聲明的變量並不會成為全局對象的屬性。也不會變動本來的屬性值,而是’遮蓋’該值。
window.PI = 3.14;
const PI = 4;
console.log(PI); // 4
console.log(window.PI); // 3.14
變量聲明提拔與暫時死區
在運用 const 和 let 來替代 var 運用時,須要關注到差別的一點是,const 和 let 不存在變量聲明提拔:
const welcome = function (name) {
console.log(welcome_text);
var welcome_text = `hello ${name}`;
};
welcome('Rainy'); // undefined
JS 引擎在掃描代碼時,碰到 var 聲明的變量會將其提拔至作用域頂部。因此在這裏,console.log() 函數接見 welcome_text 變量,變量聲明提拔以後未舉行賦值,返回 undefined。
而碰到 const 和 let 聲明的變量時,並不會將其提拔至作用域頂部,此時該變量位於暫時死區(TDZ)中,直到碰到該變量聲明語句才會移出 TDZ,在此之前接見該變量都邑拋出毛病。
const welcome = function (name) {
console.log(welcome_text);
const welcome_text = `hello ${name}`
};
welcome('Rainy'); // Uncaught ReferenceError: welcome_text is not defined
-EOF-