zoukankan      html  css  js  c++  java
  • 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(a, "b", { 
        value : 123,
        writable : false 
    });
    console.log(a.b);
    // 打印 123 a.b = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值) console.log(a.b); // 打印 123, 赋值不起作用。

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

    扩展

    Reflect.defineProperty()

     可以使用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

    Object.defineProperties

    此方法可以一次设置多个属性,例子:

    var a = {}
    Object.defineProperties(a, {
        c: {
            value: 1
        },
        d: {
            value: 2
        }
    })
    // 返回{c: 1, d: 2}

    用Object.defineProperty实现黑科技

    使 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

  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/zhaowj/p/9576450.html
Copyright © 2011-2022 走看看