ES5提供了Object.defineProperty方法,该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
语法
/*
参数1: 操作的对象
参数2: 要操作或修改的对象的键
参数3: 将被定义或修改的属性的描述符
*/
Object.defineProperty(obj, prop, descriptor)
// 栗子
Object.defineProperty(obj, 'age', {
value: 18, // 值, 默认为undefined
writable: true, // 是否能被赋值运算符改变(+、+=、/等), 默认为false
enumerable: true, // 是否能被改变, 默认为 false
configurable: true, // 是否能被枚举, 默认为false
/*
存取描述符
不可和 value writable 时出现
*/
get () { }, // get 方法返回键的值, 默认为 undefined
set (val) { } // set 方法接收新的val参数,修改键的值,默认为 undefined
});
新增属性栗子
let obj = {}
let firstName = 'JOJO'
Object.defineProperty(obj,'firstName', {
get() {
console.log('触发了get')
return firstName
},
set(val) {
console.log('触发了set')
firstName = val
}
})
obj.firstName = '鸡哥';
console.log(obj.firstName);
/*
打印输出:
触发了set // obj.firstName = '鸡哥'; 触发
触发了get // obj.firstName; 触发
鸡哥 // console.log(obj.firstName); 触发
*/
修改属性栗子
let obj = {
_firstName: 'JOJO' // 定义一个私有变量存值
};
// 新键值 避免栈溢出
Object.defineProperty(obj, 'firstName', {
get () {
console.log('get');
return this._firstName;
},
set (val) {
console.log('set');
this._firstName = val;
}
});
obj.firstName = '鸡哥';
console.log(obj.firstName);
/*
打印输出:
set
get
鸡哥
*/
深度侦听对象、侦听数组
const obj = {
firstName: 'JOJO',
age: 18,
children: {
obj2: {
firstName: '鸡哥'
},
obj3: {
firstName: '坤坤'
}
},
hobby: ['吃饭', '睡觉'],
};
function ob (params) {
if (typeof params != 'object') return;
for (const key in params) {
f(params, key, params[key]);
}
}
function f (obj, key, value) {
// 多层嵌套对象
ob(value);
Object.defineProperty(obj, key, {
get () {
console.log('get', key, value);
return value;
},
set (val) {
// 避免修改的值是一个对象
ob(val);
console.log('set', key, val);
value = val;
}
});
}
ob(obj);
obj.children.obj2.firstName = '被修改了'
/*
分别输出: 逐级遍历
get children {...}
get obj2 {...}
set firstName 被修改了
*/
obj.hobby[0] = '被修改了'
/*
分别输出:根据数组索引修改元素能被监测到
get hobby [...]
get 0 吃法
get 1 睡觉
set 0 被修改了
*/
obj.hobby.push('新增的')
/*
分别输出: 使用方法监测不到 vue 重写了数组部分方法
get hobby [...]
get 0 吃法
get 1 睡觉
*/
监控数据栗子 类似 watch
function Archiver () {
let val = null;
// 新旧值
let archiver = [];
Object.defineProperty(this, 'firstName', {
get () {
console.log('get');
return val;
},
set (value) {
console.log('set');
val = value;
archiver.unshift({ '值': value });
}
});
this.getArchiver = () => archiver;
}
// 构造函数
const obj = new Archiver();
obj.firstName = 'JOJO';
obj.firstName = '鸡哥';
console.log(obj.getArchiver());
/*
打印输出:
set
set
[ { '值': '鸡哥' }, { '值': 'JOJO' } ]
*/
标签:set,obj,val,firstName,get,Object,defineProperty,console
From: https://www.cnblogs.com/chennr/p/17584556.html