【ES6(2015)】新的声明方式 let、const
文章目錄
- 1. 作用域
- 2. let
- 3. const
1. 作用域
常見的作用域主要分為幾個(gè)類型:全局作用域、函數(shù)作用域、塊狀作用域、動態(tài)作用域。
| global/window | 全局作用域 |
| function | 函數(shù)作用域(局部作用域) |
| {} | 塊狀作用域 |
| this | 動態(tài)作用域 |
全局作用域
變量在函數(shù)或者代碼塊 {} 外定義,即為全局作用域。不過,在函數(shù)或者代碼塊{} 內(nèi)未定義的變量也是擁有全局作用域的(不推薦)。
如果變量在函數(shù)內(nèi)沒有聲明(沒有使用 var 關(guān)鍵字),該變量依然為全局變量。
// 此處可調(diào)用 course 變量function myFunction() {course = "es"// 此處可調(diào)用 course 變量 }以上實(shí)例中 course 在函數(shù)內(nèi),但是擁有全局作用域,它將作為 global 或者 window 的屬性存在。
函數(shù)作用域
在函數(shù)內(nèi)部定義的變量,就是局部作用域。函數(shù)作用域內(nèi),對外是封閉的,從外層的作用域無法直接訪問函數(shù)內(nèi)部的作用域!
如果想讀取函數(shù)內(nèi)的變量,必須借助 return 或者閉包。
function bar(value) {var testValue = 'inner'return testValue + value }console.log(bar('fun')) // "innerfun"閉包的方式:
function bar(value) {var testValue = 'inner'var rusult = testValue + valuefunction innser() {return rusult}return innser() }console.log(bar('fun')) // "innerfun"return 是函數(shù)對外交流的出口,而 return 可以返回的是函數(shù),根據(jù)作用域的規(guī)則,函數(shù)內(nèi)部的子函數(shù)是可以獲取函數(shù)作用域內(nèi)的變量的。
塊狀作用域
在ES6之前除了全局作用域就是函數(shù)作用域,一直沒有自己的塊狀作用域。在 ES6 中已經(jīng)改變了這個(gè)現(xiàn)象,塊狀作用域得到普及。關(guān)于什么是塊,只要認(rèn)識 {} 就可以了。
在這個(gè)代碼中, if后{}就是“塊”,這個(gè)里面的變量就是擁有這個(gè)塊狀作用域,按照規(guī)則, {}之外是無法訪問這個(gè)變量的。
動態(tài)作用域
在 JavaScript 中很多同學(xué)對this的指向時(shí)而清楚時(shí)而模糊,其實(shí)結(jié)合作用域會對this 有一個(gè)清晰的理解。不妨先來看下這段代碼:
在這里bind已經(jīng)把作用域的范圍進(jìn)行了修改指向了 { a: 2 },而 this 指向的是當(dāng)前作用域?qū)ο蟆?/p>
變量的作用域是在定義時(shí)決定而不是執(zhí)行時(shí)決定,也就是說詞法作用域取決于源碼,通過靜態(tài)分析就能確定,因此詞法作用域也叫做靜態(tài)作用域。 相反,只能在執(zhí)行階段才能決定變量的作用域,那就是動態(tài)作用域。
2. let
ES6 新增了let命令,用來聲明變量。
1.let 聲明的全局變量不是全局對象window的屬性
var a = 5 console.log(window.a) // 5 let a = 5 console.log(window.a) // undefined2.用let定義變量不允許重復(fù)聲明
var a = 5 var a = 6console.log(a) // 6 let a = 5 let a = 6 // VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared // at <anonymous>:1:13.let聲明的變量不存在變量提升
function foo() {console.log(a)var a = 5 }foo() //undefined上述代碼中,a 的調(diào)用在聲明之前,所以它的值是 undefined,而不是 Uncaught ReferenceError。實(shí)際上因?yàn)?var 會導(dǎo)致變量提升。而對于 let 而言,變量的調(diào)用是不能先于聲明的:
function foo() {console.log(a)let a = 5 }foo() // Uncaught ReferenceError: Cannot access 'a' before initialization4.let聲明的變量具有暫時(shí)性死區(qū)
只要塊級作用域內(nèi)存在let命令,它所聲明的變量就綁定在了這個(gè)區(qū)域,不再受外部的影響。
上面代碼中,存在全局變量 a ,但是塊級作用域內(nèi)let又聲明了一個(gè)局部變量a,導(dǎo)致后者綁定這個(gè)塊級作用域,所以在let聲明變量前,對a 賦值會報(bào)錯(cuò)。
ES6 明確規(guī)定,如果區(qū)塊中存在 let和 const 命令,這個(gè)區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報(bào)錯(cuò)。
總之,在代碼塊內(nèi),使用 let 命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時(shí)性死區(qū)”。
5.let 聲明的變量擁有塊級作用域
let實(shí)際上為 JavaScript 新增了塊級作用域
{let a = 5 } console.log(a) // undefineda 變量是在代碼塊 {} 中使用let定義的,它的作用域是這個(gè)代碼塊內(nèi)部,外部無法訪問。
3. const
不能被改變的叫做常量,ES5中定義一個(gè)常量:
Object.defineProperty(window, 'PI', {value: 3.14,writable: false }) console.log(PI) PI = 5 console.log(PI)const除了具有l(wèi)et的塊級作用域和不會變量提升外,還有就是它定義的是常量,在用 const定義變量后,我們就不能修改它了,對變量的修改會拋出異常。
const PI = 3.1415 console.log(PI) PI = 5 console.log(PI) // Uncaught TypeError: Assignment to constant variable.這個(gè)代碼塊中因?yàn)閷?PI 嘗試修改,導(dǎo)致瀏覽器報(bào)錯(cuò),這就說明 const 定義的變量是不能被修改的,它是只讀的。
注意:const 聲明的變量必須進(jìn)行初始化,不然會拋出異常 Uncaught SyntaxError: Missing initializer in const declaration。
需要注意的是,const 實(shí)際上保證的并不是變量的值不得改動,而是變量指向的那個(gè)內(nèi)存地址所保存的數(shù)據(jù)不得改動。
const obj = {name: 'xiaoming',age: 18 } obj.school = 'qinghua' console.log(obj) // {name: "xiaoming", age: 18, school: "qinghua"}雖然定義的對象是const,但是只是保證地址值不變,地址指向的內(nèi)存空間的值是可以變的。
如何讓對象或者數(shù)組這種引用數(shù)據(jù)類型也不被改變呢?
Object.freeze(obj) // 只是淺層凍結(jié),只會對最近一層的對象進(jìn)行凍結(jié),并不會對深層對象凍結(jié)。總結(jié)
以上是生活随笔為你收集整理的【ES6(2015)】新的声明方式 let、const的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java heap_javaHeap的组
- 下一篇: plaintextedit指定一行一行的