摘要:在之前,中沒有常量聲明方式,有的僅僅是一種命名上的約定。這樣就可以最大程度上規避變量的意外變化來使程序發生異常的可能性。為了避免作用域的污染,在中需要使用一個立即執行函數來確保變量的作用域范圍。
在 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-
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94935.html
摘要:在年正式發布了,簡稱,又稱為。再次簡寫循環迭代數組每個元素都執行一次回調函數。方法用于調用數組的每個元素,并將元素傳遞給回調函數。注意對于空數組是不會執行回調函數的。 轉載請注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關系。ECMA是標準,Jav...
摘要:在年正式發布了,簡稱,又稱為。再次簡寫循環迭代數組每個元素都執行一次回調函數。方法用于調用數組的每個元素,并將元素傳遞給回調函數。注意對于空數組是不會執行回調函數的。 轉載請注明出處 原文連接 http://blog.huanghanlian.com/article/5c7aa6c7bf3acc0864870f9d es6 是什么 首先弄明白ECMA和js的關系。ECMA是標準,Jav...
摘要:以下,請求兩個,當兩個異步請求返還結果后,再請求第三個此處為調用后的結果的數組對于來說,只要參數數組有一個元素變為決定態,便返回新的。 showImg(https://segmentfault.com/img/remote/1460000015444020); Promise 札記 研究 Promise 的動機大體有以下幾點: 對其 api 的不熟悉以及對實現機制的好奇; 很多庫(比...
一、語法規則 選擇器{ 屬性1:屬性值1; 屬性2:屬性值2; ...... } /*注釋*/ 二、如何在html中應用CSS 1. 外部引用css文件 css文件:css/layout.css(css文件夾和HTML位于同一個目錄下) 2. 內部嵌入css /*css代碼*/ 3...
閱讀 4133·2021-11-22 13:52
閱讀 2500·2021-11-22 13:52
閱讀 3671·2021-11-19 09:59
閱讀 1173·2021-11-17 09:33
閱讀 2435·2019-08-30 10:53
閱讀 1189·2019-08-29 17:28
閱讀 1295·2019-08-29 17:03
閱讀 3087·2019-08-26 11:31