es5實現let和const
一、let
let的特性
首先我們來看看let的特性,let用來宣告一個變數:
-
-
不能重複宣告
-
不能預處理,不存在變數提升,即未宣告之前的程式碼不能呼叫
如何實現
我們可以通過匿名函式和閉包的形式來模擬let
(function(){ var c =3 console.log(c) //1 })() console.log(c) //c is not defined
如上面的程式碼,用匿名函式的作用域來模擬塊級作用域,將用到let的程式碼放到匿名函式中,就不會造成變數汙染了
二、const
const的特性
const用於宣告一個常量,
在塊級作用域內有效
不能重複宣告
不能預處理,不存在變數提升,即未宣告之前的程式碼不能呼叫
-
他除了有和let一樣的特性外,還有自己的特性:不能修改(要注意,陣列和物件屬於引用資料型別,const儲存的是指向物件的指標,所以修改其中的屬性時指標不變,可以修改)
-
使用時必須初始化(必須賦值)
//即不能是 const c //必須 const c =1
如何實現const
這個是今天的重頭戲,要實現const我們必須瞭解js中的資料屬性和訪問器屬性,瞭解了之後說不定你自己已經有思路實現const了
資料屬性
定義在物件內部的資料有四個特徵:
-
configurable:是否可以被 delete 刪除或者改變特徵值
-
enumerable:是否能通過 for-in 迴圈遍歷返回屬性
-
writable:是否可以修改屬性的值
-
value:儲存這個屬性的資料值
訪問器屬性
指以下四個屬性:
-
configurable:能否通過 delete 刪除,能否修改屬性特性
-
enumerable:能否通過 for-in 迴圈返回屬性
-
getter:讀取屬性時呼叫的函式,預設為 undefined
-
setter:寫入屬性時呼叫的函式,預設為 undefined
用物件直接建立的屬性,其writable、enumerable和configurable 都是預設為true
看到這裡可能你已經有思路了,就是去改變這幾個屬性,還有在getter和setter中做文章
對於不可重複賦值,我們可以設定其configurable為false,同時 set中判斷是否重複賦值,如果是即報錯,而塊級作用域可以用物件作為容器創造函式作用域代替 而如何修改這些屬性呢,可以使用Object.defineProperty() 方法
Object.defineProperty(obj, prop, descriptor):會直接在一個物件上定義一個新屬性,或者修改一個物件的現有屬性,並返回此物件。
obj:要定義屬性的物件
prop:要定義或修改的屬性的名稱
descriptor:要定義或修改的屬性描述符
function _const(key, value) { window[key] = value; Object.defineProperty(window, key, { enumerable: false, configurable: false, get: function () { return value; }, set: function (newValue) { if (newValue !== value) { throw TypeError("這是隻讀變數,不可修改"); } else { return value; } }, }); }