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