zoukankan      html  css  js  c++  java
  • 双向数据绑定实现之Object.defineProperty

    vue.js利用的是es5的 defineproperty 特性实现的双向数据绑定,了解一下基本原理。

    举例

    var person= {};
    Object.defineProperty(person, "name", {
      value: '张三'
    })
    console.log(person.name); // 张三

    传参

    • 第一个参数:要设置的目标对象(必填)

    • 第二个参数:需要定义的属性或方法的名称(必填)

    • 第三个参数:目标属性所拥有的特性。(descriptor)(必填)

          三个参数都是必填项,重点介绍第三个参数 descriptor

    descriptor

    • value:属性的值

    • writable:如果为false,属性的值就不能被重写, 只能为只读了

    • configurable:总开关,一旦为false,就不能再设置他的(value,writable,configurable)

    • enumerable:是否可枚举(是否能在for...in循环中遍历出来或在Object.keys中列举出来)

    • get:一会细说

    • set:一会细说

    descriptor 默认值

    回头看第一个例子

    var person= {};
    Object.defineProperty(person, "name", {
      value: '张三'
    })
    console.log(person.name); // 张三

    我们只设置了 value,别的并没有设置

    但是第一次的时候 可以简单的理解为(暂时这样理解)它会默认帮我们把writable,configurable,enumerable都设上值,而且值还都是false。

    也就是说,上面代码和下面是等价的的(仅限于第一次设置的时候)。

    var person = {};
    Object.defineProperty(person ,"name",{
      value: '张三',
      writable :false,
      enumerable: false,
      configurable: false
    });
    console.log(person.name); // 张三

    configurable

    总开关,第一次设置 false 之后,,第二次什么设置也不行了,比如说

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

    就会报错了。。

    注意上面讲的默认值。。。如果第一次不设置它会怎样。。会帮你设置为false。。所以。。第二次。再设置他会怎样?。。对喽,,会报错

    writable

    如果设置为fasle,就变成只读了。。

    var person = {}; 
    Object.defineProperty(person, "name", { 
          value : '张三',
          writable : false 
      }
    ); console.log(person.name);
    // 打印 张三 person.name = '李四'; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值) console.log(person.name); // 打印 张三, 赋值不起作用。

    enumerable

    属性特性 enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。

    var person = {}; 
    Object.defineProperty(person, "name", { 
          value : '张三',
          enumerable: true
      }
    );
    console.log(Object.keys(person)); // 打印 ["name"]
    如果将enumerable改为false, for...in 类似
    var person = {}; 
    Object.defineProperty(person, "name", { 
          value : '张三',
          enumerable: false
      }
    );
    console.log(Object.keys(person)); // 打印 []

    set 和 get

    在 descriptor 中不能同时设置访问器(get 和 set)和 wriable 或 value,否则会错,就是说想用 get 和 set,就不能用 writable 或 value 中的任何一个。

    var person= {};
    var temp = [];
    Object.defineProperty(person, 'name', {
      set: function(newVal) {
        temp['name'] = newVal;
        console.log('为person设置新的姓名:' + newVal);
      },
      get: function() {
        var _name =  temp['name'] || '默认姓名';
        console.log('获取person的姓名:' +  _name);
        return _name;
      }
    });
    person.name = '张三';      // 打印 获取person的姓名:张三
    console.log(person.name)  // 打印 获取person的姓名:张三(如果不设置name,这里会打印'默认姓名')

    简单来说,这个 “name” 赋值或者取值的时候会分别触发 set 和 get 对应的函数。

    作者:杨川宝

    原文链接:解析神奇的 Object.defineProperty

    进一步学习: vue 源码分析之如何实现 observer 和 watcher

  • 相关阅读:
    浅析Java中的final关键字
    浅谈JAVA集合框架
    While reading XXX pngcrush caught libpng error: N
    git/svn里面的merge和rebase区别
    kvc kvo 总结---180313
    iOS 拨打电话三种方式总结
    IOS中获取各种文件的目录路径的方法-备
    文件管理系统-备
    iOS界面调试工具 Reveal-备用
    十六进制string转换UIColor -备用
  • 原文地址:https://www.cnblogs.com/lvmylife/p/7474374.html
Copyright © 2011-2022 走看看