这是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