用过vue的小伙伴都知道当状态发生改变的时候会自动更新视图,那具体的事先原理是什么呢?Javascript侦测变化有两个方式,有
Object.defineProperty
和Proxy
,Proxy
是ES6新加的,目前浏览器支持度不是很好,Vue目前底层还是用的是Object.defineProperty
,所以想要深入了解Vue底层侦测变化原理,必须有必要要好好学习下Object.defineProperty
。
对象的属性有以下几种:
- 命名属性:可通过
.
直接访问到的属性。 - 数据属性:专门保存一个值的属性。
- 访问器属性:保护数据属性的特殊属性。
- 内部属性:不能通过
.
直接访问的属性,比如class
和__proto__
。
数据属性
WechatIMG298.jpeg
如果
configurable
设为false,那么delete删除无效,并且无法修改其他属性。
// 1)对象直接量;属性特性默认为true
var o1 = {
name: 'tom'
};
console.log(Object.getOwnPropertyDescriptor(o1, 'name'));
// => Object {value: "tom", writable: true, enumerable: true, configurable: true}
// 2)通过Object.create创建,属性特性默认为false
var o2 = Object.create(null, {
name: {value:'tom'}
});
console.log(Object.getOwnPropertyDescriptor(o2, 'name'));
// => Object {value: "tom", writable: false, enumerable: false, configurable: false}
1.在使用Object.defineProperty、Object.defineProperties 或 Object.create 函数的情况下添加数据属性,writable、enumerable和configurable默认值为false。
2.使用对象直接量创建的属性,writable、enumerable和configurable特性默认为true。
访问器属性
WechatIMG230.jpeg
var obj = {};
// 添加一个属性,并设置为访问器属性
Object.defineProperty(obj, "name", {
get: function () {
return this._name; // get和set里的变量不要使用属性,如:属性为name,get和set用的是_name
},
set: function (x) {
if (isNaN(x)) {
this._name = x;
} else {
this._name = 'name不能为纯数字';
}
},
enumerable: true,
configurable: true
});
console.log(Object.getOwnPropertyDescriptor(obj, 'name')); // => Object {get: function, set: function, enumerable: true, configurable: true}
obj.name = '12';
console.log(obj.name); // => name不能为纯数字