摘要:塊級聲明塊級聲明是用于聲明在指定塊的作用域之外無法訪問的變量。美元符號可以放到任何一個位置,甚至多帶帶一個美元符號。塊級函數從開始,在嚴格模式下,塊里的函數作用域為這個塊。
持續更新的github筆記,鏈接地址:Front-End-Basics
此篇文章的筆記地址:字符到底發生了什么變化
ES6走走看看系列,特別鳴謝奇舞讀書會~
塊級作用域又稱詞法作用域,存在于:函數內部(函數作用域)
塊中(字符 { 和 } 之間的區域)
注意:ES6允許塊級作用域任意嵌套
{{{{{{let text = "Hello World!"}}}}}}
因為有了塊級作用域,然后我們才有繼續往下聊的可能。
1、 塊級聲明塊級聲明是用于聲明在指定塊的作用域之外無法訪問的變量。
2、 let聲明:用來聲明一個塊級作用域變量1、 聲明的變量具有塊級作用域的特性
// 例子 function getValue (condition) { if (condition) { let value = "blue"; return value; } console.log(value) // 報錯 value is not defined } getValue()
2、 在同一個作用域內不能使用let聲明同名的變量
// 不管是var,const或者let,新的let聲明之前同名的變量,都會報錯 var count = 30; let count = 40; // 報錯 Identifier "count" has already been declared // 函數形參和函數內部的let聲明變量重名,報錯 function test(value) { let value = 3; } test() // 報錯 Identifier "value" has already been declared // 在不同的作用域聲明的變量重名是沒問題的 let count = 30; if(true) { let count = 40; // 不同的作用域,不會報錯 }
3、 聲明沒有預解析,不存在變量提升,有“臨時死區”(TDZ)
從塊的開始到變量聲明這段的區域被稱為臨時死區,ES6明確規定,如果區塊中存在let和const命令,則這個區塊對這些命令聲明的變量從一開始就形成封閉作用域,只要在聲明之前就使用這些變量(賦值,引用等等),就會報錯。
if(true) { console.log(typeof value); // 報錯 value is not defined let value = "blue"; }
注意:TDZ是區域是“塊開始”到“變量聲明”,下面的例子不報錯
// typeof 說是相對安全,確實是,永遠拿不到想要的結果 console.log(typeof value); // 打印 undefined,沒有報錯 if(true) { let value = "red"; }3、 const聲明:聲明常量(如PI),值一旦被設定后不可更改
1、 常量聲明的值是不可變的
注意:const聲明的對象不允許修改綁定,但可以修改該對象的屬性值。
const number = 6; number = 5; // 報錯 Assignment to constant variable const obj = {number: 1}; obj.number = 2; // 不報錯 obj = {number: 3}; // 報錯 Assignment to constant variable
2、 因為常量聲明后值就不可更改了,所以聲明時必須賦值
// 有效的常量 const count = 30; // 報錯 Missing initializer in const declaration const name;
3、 聲明的常量具有塊級作用域的特性
if(true) { const number = 5; } console.log(number) // 報錯 number is not defined
4、 在同一個作用域內不能使用const聲明同名的變量
var message = "Hello"; let age = 25; // 這兩條語句都會報錯 const message = "Good"; const age = 30;
5、 聲明沒有預解析,不存在變量提升,有“臨時死區”(TDZ)
總結:一張表格
聲明方式 | 變量提升 | 作用域 | 是否需要初始值 | 重復定義 |
---|---|---|---|---|
var | 是 | 函數級 | 不需要 | 允許 |
let | 否 | 塊級 | 不需要 | 不允許 |
const | 否 | 塊級 | 需要 | 不允許 |
擴展:再提一下變量命名,不管是var、let、const聲明的變量名,可以由數字,字母,下劃線及美元符號組成,但是不能以數字開頭。美元符號可以放到任何一個位置,甚至多帶帶一個美元符號。
4、 循環中的塊作用域綁定循環中的let聲明
// 第一個對比 // before for(var i = 0; i < 5; i++) { // ... 省略一些代碼 } console.log(i) // 5 //after for(let i = 0; i < 5; i++) { // ... 省略一些代碼 } console.log(i) // 報錯 i is not defined // 第二個對比 // before var funcs = []; for(var i = 0; i < 10; i++) { funcs.push(() => {console.log(i)}) } funcs.forEach((ele) => { ele() }) // 打印 10次 10 // after var funcs = []; for(let i = 0; i < 10; i++) { funcs.push(() => {console.log(i)}) } funcs.forEach((ele) => { ele() }) // 打印 0 1 2 3 4 5 6 7 8 9
注意:有一點很重要,let 聲明在循環內部的行為是標準中專門定義的,它不一定與 let 不提升特性有關。
循環中的const聲明
// for 循環會報錯 for (const i = 0; i < 1; i++) { console.log(i) } // 打印 0 ,然后報錯 Assignment to constant variable. // for-in 和 for-of 不會報錯 var object = { a: true, b: true, c: true }; for (const key in object) { // 不要在循環體內更改key的值,會報錯 console.log(key) } // 打印 a b c
注意:const可以應用在 for-in 和 for-of 循環中,是因為每次迭代不會修改已有綁定,而是會創建一個新綁定。
5、 塊級綁定最佳實踐的進化ES6 早期
普遍認為默認使用let來替代var,對于寫保護的變量使用const
ES6 使用中
普遍默認使用const,只有確實需要改變變量的值時使用let。因為大部分變量的值在初始化后不應再改變,而預料之外的變量值的改變是許多bug的源頭。這樣就可以在某種程度上實現代碼的不可變,從而防止某些錯誤的發生。
6、 全局變量將逐步與頂層對象的屬性脫鉤頂層對象,在瀏覽器環境指的是window對象,在Node指的是global對象。
為了保持兼容性,var命令和function命令聲明的全局變量,依舊是頂層對象的屬性;
var a = 1; window.a // 1
另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性。
上圖可見let 聲明的變量,并沒有在Window對象里,而是一個新的Script對象。
擴展:如果需要在瀏覽器中跨frame或window訪問代碼,仍然可以用var在全局對象下定義變量。
7、 塊級函數從ECMAScript 6開始,在嚴格模式下,塊里的函數作用域為這個塊。ECMAScript 6之前不建議塊級函數在嚴格模式下使用。
"use strict"; function f() { return 1; } { function f() { return 2; } } f() === 1; // true // f() === 2 在非嚴格模式下相等
注意:在非嚴格模式下不要用塊級函數,因為在非嚴格模式下,塊中函數的聲明表現奇怪,有兼容性風險
if (shouldDefineZero) { function zero() { // DANGER: 兼容性風險 console.log("This is zero."); } }
ECMAScript 6中,如果shouldDefineZero是false,則永遠不會定義zero,因為這個塊不執行。這是新標準定義的。然而,這里存在歷史遺留問題,無論這個塊是否執行,一些瀏覽器會定義zero。
在嚴格模式下,所有支持ECMAScript 6的瀏覽器以相同的方式處理:只有在shouldDefineZero為true的情況下定義zero,并且作用域只是這個塊內。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/97515.html
摘要:外層作用域不報錯正常輸出塊級作用域與函數聲明規定,函數只能在頂層作用域和函數作用域之中聲明,不能在塊級作用域聲明。規定,塊級作用域之中,函數聲明語句的行為類似于,在塊級作用域之外不可引用。同時,函數聲明還會提升到所在的塊級作用域的頭部。 前言:最近開始看阮一峰老師的《ECMAScript 6 入門》(以下簡稱原...
摘要:聲明之函數作用域和全局作用域。塊級作用域不能重復聲明臨時性死區等特性用來解決變量存在的種種問題。塊級作用域終于在外面訪問不到了。一些常量聲明使用聲明的變量名全部大寫。 ES5之前javascript語言只有函數作用域和全局作用域,使用var來聲明變量,var聲明的變量還存在變量提升使人困惑不已。我們先來復習一下ES5的var聲明,再對比學習let和const 。 var var聲明之函...
摘要:要理解閉包,首先必須理解特殊的變量作用域。使用閉包有一個優點,也是它的缺點就是可以把局部變量駐留在內存中,可以避免使用全局變量。 js閉包 閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的常見的方式,就是在一個函數內部創建另一個函數,通過另一個函數訪問這個函數的局部變量。要理解閉包,首先必須理解Javascript特殊的變量作用域。變量的作用域無非就是兩種:全局變量和局部變量...
閱讀 1335·2021-10-27 14:14
閱讀 3585·2021-09-29 09:34
閱讀 2489·2019-08-30 15:44
閱讀 1734·2019-08-29 17:13
閱讀 2579·2019-08-29 13:07
閱讀 881·2019-08-26 18:26
閱讀 3353·2019-08-26 13:44
閱讀 3219·2019-08-26 13:37