在vue2中经常会听到这个属性,我也是联系了很多遍,奈何在工作中很少能用到,所以看了忘,忘了看,索性自己写下来记录一下,方便以后随时翻阅。
Object.defineProperty(obj, prop, descriptor)
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
这是mdn的描述,嗯,看了和没看一样。来看一下它的三个参数:
- obj 要定义属性的对象。
- prop 要定义或修改的属性的名称或 Symbol 。
- descriptor 要定义或修改的属性描述符。
接下来就直接通过代码来揣摩一下这个方法!
首先我们定义一个普通的对象。
let obj = {
a: 1,
b: 2,
c: 3,
}
接下来通过defineProperty给obj添加一个新的属性。
Object.defineProperty(obj, 'name', {
value: 'yzl'
})
控制台输出一下obj,发现被代理的属性和其他属性会有颜色的差异,被代理的属性会比较浅。
接下来对被代理的属性进行删,改操作并输出。
obj.name = 'sultan' // obj的name依然为yzl,因为被代理了的属性为不可变更
delete obj.name;
输出后发现,name的值还是yzl。 说明修改和删除操作都是被了,这是因为被代理的属性默认是不可删改的,可以通过第三个参数 descriptor来控制权限。
Object.defineProperty(obj, 'age', {
value: 12,
writable: true, // 描述属性是否可以被修改。默认为 false。
configurable: true, // 描述属性是否可以被删除,修改。 默认false
enumerable: true, // 描述属性是否可以被枚举。 默认为false
})
这里有一个enumerable, 该属性标识是否可以被枚举。 枚举的意思就是,当你通过for in循环会不会遍历到该属性
除了这些描述符,还有一对比较特殊的方法。
get和set。
Object.defineProperty(obj, 'address', {
get() {
return '大连'
},
set(value) {
console.log(value)
}
})
get函数在属性被读取时候触发,set函数在属性被修改时候触发。注意get,和set不能和value或writable同时出现,否则会报错。因为value已经指定了值,get函数也是返回一个值
下面以一个需求的形式讲述get,set的用法。
现在有一个变量 pet = dag,想要给上边的obj新增一个myPet的属性,值同步变量pet的值,就可以这么写。
let pet = 'dog';
Object.defineProperty(obj, 'pet', {
get() {
return pet;
},
set(value) {
pet = value;
}
})
pet = 'cat';
这样的话每当你改变pet的值,obj中的myPet就会自行更新,将两个不相关的变量关联在了一起~
使用defineProperty模拟实现vue的响应式数据(一层实现)
function mVue(option) {
const { data } = option;
let obj = {};
this.observer.call(obj, data);
this.observer(data)
this._data = obj;
}
mVue.prototype.observer = function(params) {
const keys = Object.keys(params);
keys.forEach(key=> {
Object.defineProperty(this, key, {
get: function reactiveGetter() {
return params[key]
},
set: function reactiveSetter(value) {
params[key] = value;
}
})
})
}
const mvm = new mVue({
data: {
name: 'sultan',
address: '杭州',
children: [
{
name: 'xiaoming',
age: '20',
},
{
name: 'xiaohong',
age: '18'
}
],
obj: {
a: {
b: 1,
}
}
}
})