這是js中一個很是重要的方法,ES6中某些方法的實現依賴於它,VUE經過它實現雙向綁定html
此方法會直接在一個對象上定義一個新屬性,或者修改一個已經存在的屬性, 並返回這個對象vue
Object.defineProperty(object, attribute, descriptor)this
這三個參數都是必輸項編碼
第一個參數爲目標對象spa
第二個參數爲須要定義的屬性或者方法雙向綁定
第三個參數爲目標屬性所擁有的特性code
前兩個參數都很明確,重點是第三個參數 descriptor, 它有如下取值htm
value: 屬性的值對象
writable: 屬性的值是否可被重寫(默認爲false)blog
configurable: 總開關,是否可配置,若爲false, 則其餘都爲false(默認爲false)
enumerable: 屬性是否可被枚舉(默認爲false)
get: 獲取該屬性的值時調用
set: 重寫該屬性的值時調用
一個例子
var a= {} Object.defineProperty(a,"b",{ value:123 }) console.log(a.b) //123 a.b = 456 console.log(a.b) //123 a.c = 110 for (item in a) { console.log(item, a[item]) //c 110 }
由於 writable 和 enumerable 默認值爲 false, 因此對 a.b 賦值無效,也沒法遍歷它
總開關,是否可配置,設置爲 false 後,就不能再設置了,不然報錯, 例子
var a= {} Object.defineProperty(a,"b",{ configurable:false }) Object.defineProperty(a,"b",{ configurable:true }) //error: Uncaught TypeError: Cannot redefine property: b
是否可重寫
var a = {}; Object.defineProperty(a, "b", { value : 123, writable : false
});
console.log(a.b); // 打印 123 a.b = 25; // 沒有錯誤拋出(在嚴格模式下會拋出,即便以前已經有相同的值) console.log(a.b); // 打印 123, 賦值不起做用。
屬性特性 enumerable 定義了對象的屬性是否能夠在 for...in 循環和 Object.keys() 中被枚舉
var a= {} Object.defineProperty(a,"b",{ value:3445, enumerable:true }) console.log(Object.keys(a));// 打印["b"]
enumerable改成false
var a= {} Object.defineProperty(a,"b",{ value:3445, enumerable:false //注意咯這裏改了 }) console.log(Object.keys(a));// 打印[]
若是設置了 set 或 get, 就不能設置 writable 和 value 中的任何一個,不然報錯
var a = {} Object.defineProperty(a, 'abc', { value: 123, get: function() { return value } }) //Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object> at Function.defineProperty
對目標對象的目標屬性 賦值和取值 時, 分別觸發 set 和 get 方法
var a = {} var b = 1 Object.defineProperty(a,"b",{ set:function(newValue){ b = 99; console.log("你要賦值給我,個人新值是"+newValue); }, get:function(){ console.log("你取個人值"); return 2 //注意這裏,我硬編碼返回2 } }) a.b = 1 //打印 你要賦值給我,個人新值是1 console.log(b) //打印 99 console.log(a.b) //打印 你取個人值 //打印 2 注意這裏,和個人硬編碼相同的
上面的代碼中,給a.b賦值,b的值也跟着改變了。緣由是給a.b賦值,自動調用了set方法,在set方法中改變了b的值。vue雙向綁定的原理就是這個。
可使用ES6的靜態方法 Reflect.defineProperty(), 使用起來和 Object.defineProperty 徹底同樣,惟一的不一樣是修改屬性的配置出錯時,返回false, 不拋錯。 例子:
var a = {} Reflect.defineProperty(a, "b", { value: 2, configurable: false }) Reflect.defineProperty(a, "b", { value: 2, configurable: true }) // 返回false
var a = {} Reflect.defineProperty(a, "b", { value: 2, configurable: false }) Object.defineProperty(a, "b", { value: 2, configurable: true }) //Uncaught TypeError: Cannot redefine property: b at Function.defineProperty (<anonymous>) at <anonymous>:6:8
此方法能夠一次設置多個屬性,例子:
var a = {} Object.defineProperties(a, { c: { value: 1 }, d: { value: 2 } }) // 返回{c: 1, d: 2}
使 a==1 && a==2 && a==3 爲true
var b = 1 Object.defineProperty(window, "a", { get: function() { return b++ } }) console.log(a==1 && a==2 && a==3) //返回true
除此以外,還能夠用對象的 toString() 方法來實現
var a = { b: 1, toString() { return this.b++ } } console.log(a==1 && a==2 && a==3) //返回true
ps: 這是本人在博客園寫的第一個博客,歡迎你們多對支持和提出意見建議
參考:https://www.cnblogs.com/weiqu/p/5860945.html