vue.js中使用ES5的Object.defineProperty()实现数据的双向绑定vue
Object.defineProperty()能够用来修改对象的属性,也能够在对象上新建立一个属性函数
Object.defineProperty(obj, prop, descriptor)spa
参数: obj -> 被定义或修改属性的对象 双向绑定
prop -> 要定义或修改的属性名称code
descriptor -> 对属性的描述对象
函数将返回传递给他的obj对象自己blog
该方法容许开发者精确的对对象属性的定义和修改。经过正常赋值进行属性添加而构建的属性会被枚举器方法(如for..in循环或Object.keys方法)获取,从而致使属性值被外部方法改变或删除。而Object.defineProperty()能够避免以上描述的状况,默认的,经过Object.defineProperty()添加的属性是默认不可改变的。
属性描述参数(descriptor)主要由两部分构成:数据描述符(data descriptor)和访问器描述符(accessor descriptor)。数据描述符就是一个包含属性的值,并说明这个值可读或不可读的对象;访问器描述符就是包含该属性的一对getter-setter方法的对象。一个完整的属性描述(descriptor)必须是这二者之一,而且不能够二者都有。ip
value:属性的值,默认为undefined开发
writable:可重写性,若是为false,属性的值就不能被重写, 只能为只读了,默认为falseget
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); // 张三
总开关,第一次设置 false 以后,第二次什么设置也不行了,好比说
var person = {}; Object.defineProperty(person,"name",{ configurable: false }); Object.defineProperty(person,"name",{ configurable: true }); //error: Uncaught TypeError: Cannot redefine property: name
就会报错了。。
注意上面讲的默认值。。。若是第一次不设置它会怎样。。会帮你设置为false。。因此。。第二次。再设置会报错
若是设置为fasle,就变成只读了,不能进行修改。。
var person = {}; Object.defineProperty(person, "name", { value : '张三', writable : false
}
); console.log(person.name); // 打印 张三 person.name = '李四'; // 没有错误抛出(在严格模式下会抛出,即便以前已经有相同的值) console.log(person.name); // 打印 张三, 赋值不起做用。
属性特性 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)); // 打印 []
在 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,这里会打印'默认姓名')