Object.defineProperty()方法学习笔记

这是js中一个非常重要的方法,ES6中某些方法的实现依赖于它,VUE通过它实现双向绑定

参数

Object.defineProperty(object, attribute, descriptor)

这三个参数都是必输项

第一个参数为目标对象

第二个参数为需要定义的属性或者方法

第三个参数为目标属性所拥有的特性

前两个参数都很明确,重点是第三个参数 descriptor, 它有以下取值

descriptor

value: 属性的值

writable: 属性的值是否可被重写(默认为false)

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 赋值无效,也无法遍历它

configurable

总开关,是否可配置,设置为 false 后,就不能再设置了,否则报错, 例子

var a= {}
Object.defineProperty(a,"b",{
  configurable:false
})
Object.defineProperty(a,"b",{
  configurable:true
})
//error: Uncaught TypeError: Cannot redefine property: b

writable

是否可重写

var a = {}; 

Object.defineProperty(o, "b", { 
    value : 123,
    writable : false });

console.log(a.b); // 打印 37
a.b = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
console.log(o.a); // 打印 37, 赋值不起作用。

enumerable

属性特性 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

如果设置了 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双向绑定的原理就是这个。

参考:https://www.cnblogs.com/weiqu/p/5860945.html

猜你喜欢

转载自www.cnblogs.com/zhaowj/p/9576450.html