ES6 實現了類的概念 ES5使用函數模擬 ES6中的 class定義一個類, 其內部包含 構造函數, 除了在構造函數顯示的定義一些屬性, 其餘的預設都添加到這個類的原型對象上。 在一個類中定義一個讀取名字的函數: 如果我們把 sayName 這個函數拿出來運行會是什麼結果呢? 繼以上代碼 以上報錯 ...
ES6 實現了類的概念
class Prosen {
}
ES5使用函數模擬
function Prosen() {
}
ES6中的 class定義一個類, 其內部包含 constructor
構造函數, 除了在構造函數顯示的定義一些屬性, 其餘的預設都添加到這個類的原型對象上。
在一個類中定義一個讀取名字的函數:
class Prosen {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name)
}
}
const prosen = new Prosen('zhangsan')
prosen.sayName() //張三
如果我們把 sayName 這個函數拿出來運行會是什麼結果呢?
繼以上代碼
const prosen1 = new Prosen('lisi')
const { sayName } = prosen1
sayName() // 報錯
以上報錯的原因是 sayName
函數中的 this不對。指向的不是 prosen1這個實例對象,所以是無法讀取name
屬性的。
使用 proxy來代理實例對象,攔截讀取操作並修改this的指向
function classProxy(target) {
const m = WeakMap()
// 讀取攔截配置, 只需要配置 get
const hanlder = {
get(target, key) {
const val = Reflect.get(target, key)
// 要獲取的是函數執行, 如果不是函數就直接返回 val
if (typeof val !== 'function') return val
if (!m.has(val)) {
// 使用 bind改變運行函數的 this為攔截的實例對象
m.set(val, val.bind(target))
}
return m.get(val)
}
}
const proxy = new Proxy(target, hanlder)
return proxy
}
繼以上代碼
const prosen2 = new Prosen('qiqingfu')
const { sayName } = classProxy(prosen2)
sayName() // qiqingfu
以上代碼 classProxy(prosen2)
返回的是包含一層攔截器的實例對象, 當讀取 sayName
這個函數的是和會出發 get
攔截等操作。
總結其它知識點
proxy: 攔截器, 用於對象操作的自定義行為(如屬性查找, 賦值, 枚舉, 函數調用, 是實例化等)
Reflect 是一個內置的對象, 它提供攔截 Javascript方法,和Object操作類似。
WeakMap: 可以實現對象 值-值的對應, 並且一個對象的鍵值只能是對象,且不計入垃圾回收機制,可對象引用常駐記憶體造成的記憶體泄漏等問題。
WeakMap:
const n = {a: 1}
const m = new WeakMap()
m.set(n, 1)
m.get(n) // 1
m.has(n) // true