Object.defineProperty也稱 “對象屬性攔截器”
攔截器不懂?(這可是個好東西,懂得話請跳過這一部分)
比如你平常用 Person.name就可以獲取到 Person的 name屬性的值對吧,但是如果我給該 name屬性設置個攔截器,那你獲取的可不一定是我 name屬性的值咯(嘻嘻嘻),因爲我可以在攔截器裏操作,並且返回給你任何值,比如下面這個例子,你永遠獲取不到 age的真實值,控制檯只能打印 ‘別質疑我的年齡,我18’。
let Person = {
name: 'besam-juajua',
age: '18'
}
Object.defineProperty(Person, 'age', {
enumerable: true,
configurable: false,
get () {
return '別質疑我的年齡,我18'
}
})
console.log(Person.age);
當然,除了 get,還有 set,defineProperty接收三個參數,第一個要攔截的對象,第二個要攔截的屬性,第三個是要攔截的操作(俗稱 “描述”,是一個對象來的),那麼可以攔截哪些操作呢?如下(一共有六個):
value: 值 // 給改屬性賦值
writable: true // 該屬性是否可寫
enumerable: true, // 該屬性是否可枚舉,不理解的話,你可以理解爲 “是否可for...in”來遍歷
configurable: false, // 是否可重新配置
get: function (value) { // 當獲取該屬性時,自動調用該方法 }
set: function (value) { // 當設置該屬性時,自動調用該方法 }
相信你已經基本瞭解 defineProperty了,下面講下該例子的一個典型應用(實現數據雙向綁定):
試試吧!創建一個 id 爲 bindData 的輸入框,然後插入這片代碼(你可以在控制檯和input裏改變 Person.name的值,查看結果)
// 創建一個將要雙向綁定的對象
var Person = { name: '' }
// input輸入每一個字符,都將其數據傳到Person,這就先實現了單向綁定
$('#bindData').on('input',function(e){Person.name = e.target.value});
// 在控制檯每改變一次Person.name,都會將新值傳到input輸入框
Object.defineProperty(Person,'name',{
enumerable: true,
configurable: true,
get: function(){return this._name||'besam-juajua'},
set: function(value){
this._name = value;
$('#bindData').value = value;
console.log("Person.name = " + Person.name)
console.log("input = " + $('#bindData').val())
}
})
很簡單吧,關於 Object.defineProperty, 你需要注意:
不能 writable 和 (set、get) 同時存在,有前者不能有後者,有後者不能有前者,因爲同時存在的話,就互相矛盾了
關於 get 和 set 裏面,爲什麼要用 this._name , 不明白的話,看我下一篇博客。。。