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

    前言

    vue.js中使用ES5的Object.defineProperty()实现数据的双向绑定

    Object.defineProperty()原理

    Object.defineProperty()可以用来修改对象的属性,也可以在对象上新创建一个属性

    语法

    Object.defineProperty(obj, prop, descriptor)

    参数: obj -> 被定义或修改属性的对象 

        prop -> 要定义或修改的属性名称

           descriptor -> 对属性的描述

    返回值

    函数将返回传递给他的obj对象本身

    描述符(descriptor)说明

    该方法允许开发者精确的对对象属性的定义和修改。通过正常赋值进行属性添加而构建的属性会被枚举器方法(如for..in循环或Object.keys方法)获取,从而导致属性值被外部方法改变或删除。而Object.defineProperty()可以避免以上描述的情况,默认的,通过Object.defineProperty()添加的属性是默认不可改变的。 
    属性描述参数(descriptor)主要由两部分构成:数据描述符(data descriptor)和访问器描述符(accessor descriptor)。数据描述符就是一个包含属性的值,并说明这个值可读或不可读的对象;访问器描述符就是包含该属性的一对getter-setter方法的对象。一个完整的属性描述(descriptor)必须是这两者之一,并且不可以两者都有。

    数据描述符

    • value:属性的值,默认为undefined

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

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

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

    访问器描述符

    • get:获取数据时触发

    • set:设置数据时触发

    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,这里会打印'默认姓名')
  • 相关阅读:
    博客园主题备份
    NT6 HDD Installer 3.1.3(硬盘直接重装Win7/Win8/Windows 2008系统)
    C# 自动投票和手机号码归属地查询 简单程序源码分享(高手飘过)
    Android 开发最简单的快速拨打器(含源码)
    学Android的开始
    Android 图片浏览器Gallery的简单应用
    WordPress设置定时发布文章,且发布之前无404可以正常访问(手动修改代码,无需插件)
    EJB3.0JPA实体的注解规范以及Hibernate特有的扩展
    验证码技术
    数据库索引
  • 原文地址:https://www.cnblogs.com/kunmomo/p/9953215.html
Copyright © 2011-2022 走看看