的確寫Proxy文章很多,那麼今天我也不湊字數了,炒兩個栗子吧。
一、虛擬屬性
const person = {
name: 'xiaoyun',
province: '江蘇省',
city: '南京市'
}
複製程式碼
對於上述物件,我們可能需要地址資訊(由省市拼接而成),在此之前我們可能會採取下列方式:
- 直接在person物件上宣告一個address屬性;
- 當用到address資訊時,再通過person拼接。
第一個方法的主要弊端是汙染了原有的物件,而第二種方法就很不靈活。現在我們可以通過Proxy實現比較好的效果:
const enhancePerson = new Proxy(person, {
get (target, name) {
switch (name) {
case 'address':
return `${target['province']}-${target['city']}`
default:
return target[name]
}
}
})
enhancePerson.address // 江蘇省-南京市
複製程式碼
通過這種方式我們就可以實現虛擬屬性了,因為它不會被遍歷出來:
Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
複製程式碼
這裡還有一個我覺得比較容易忽略的點:
person === enhancePerson // false
enhancePerson.city = '蘇州市'
enhancePerson.city === person.city // true
複製程式碼
顯然這兩個並不是同一個物件,但是我通過改變enhancePerson的city屬性卻影響到了person的city屬性,這就是我們通常會忽略掉的,如果你不設定Proxy的set方法,它會保持預設行為:
set (target, propKey, value) {
target[propKey] = value
}
複製程式碼
可能有些同學會想不就是不讓它遍歷出來嗎?看這招:
const person = {
name: 'xiaoyun',
province: '江蘇省',
city: '南京市',
get address () {
return `${this.province}-${this.city}`
}
}
const enhancePerson = new Proxy(person, {
ownKeys (target) {
return Object.keys(target).filter(item => item !== 'address')
}
})
enhancePerson.address // 江蘇省-南京市
Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
複製程式碼
雖然是實現了上述的功能,但是Proxy中的ownKeys攔截的方法太多,所以我們攔截ownKeys之後,會導致某些方法無法使用,並且攔截ownKeys返回的結果也有嚴格的要求:
- 返回的結果必須是一個陣列
- 並且陣列的元素必須是String或者Symbol型別
- 結果必須包含物件的所有不可配置、自身擁有的屬性
- 如果物件不能擴充套件,則結果只能包含自身擁有的屬性,不能含有其他屬性
所以在攔截方法注意點很多,不然很容易出現問題。
Tip: 未通過defineProperty定義的屬性的描述器屬性預設為true,否則預設為false。
二、擴充套件基本操作
當我第一次接觸Python時,比較有印象的就是它的List的一個語法: arr[1:3],以前只有羨慕的份,現在完全可以自己擼一個:
const arr = [1, 2, 3, 4, 5, 6, 7, 8]
const list = new Proxy(arr, {
get (target, name) {
if (name.includes(':')) {
const indexs = name.split(':')
return target.slice(indexs[0], indexs[1])
}
return target[name]
}
})
list['2:6'] // [ 3, 4, 5, 6 ]
複製程式碼
是不是?,對於物件,我們同樣可以採用類似的方法:
const obj = {
a: {
b: {
c: 'xiaoyun'
}
}
}
const obj1 = new Proxy(obj, {
get (target, name) {
const keys = name.split('.')
return keys.reduce((pre, next) => {
if (pre !== null && pre !== undefined) {
pre = pre[next]
}
return pre
}, target)
}
})
obj1['a.b.c'] // xiaoyun
複製程式碼
喜歡本文的小夥伴們,歡迎關注我的訂閱號超愛敲程式碼,檢視更多內容.