概念
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
学习路线
想必学习过前端的人都或多或少的了解过 Object.defineProperty ,但是并不了解怎么使用或深入研究,这里我就带大家系统的学习一下。
定义属性
语法:Object.defineProperty(obj, prop, descriptor)
let obj = {}Object.defineProperty(obj, 'name', { value: 'hello'})console.log(obj.name); // hello
复制代码
通过这样定义的属性是不可枚举的,就不能进行 for in
不可枚举
let obj = {}Object.defineProperty(obj, 'name', { enumerable: true, value: 'hello'})for(let key in obj){ console.log(key);}
复制代码
添加 enumerable: true 就变成了可枚举属性
不可配置
let obj = {}Object.defineProperty(obj, 'name', { enumerable: true, value: 'hello'})delete obj.nameconsole.log(obj.name); // hello
复制代码
我们在 delete obj.name 之后,发现结果并没有发生任何改变,也就是说这个属性不可配置
let obj = {}Object.defineProperty(obj, 'name', { enumerable: true, // 枚举 configurable: true, // 配置 value: 'hello'})delete obj.nameconsole.log(obj.name); // undefined
复制代码
通过添加 configurable: true 来实现数据配置
不可重写
let obj = {}Object.defineProperty(obj, 'name', { enumerable: true, // 枚举 configurable: true, // 配置 writable: true, // 重写 value: 'hello'})obj.name = 'world'console.log(obj.name);
复制代码
在此之前,我们修改 obj.name 的值,并没有实现,添加 configurable: true 后可以达到重写的效果
实现拦截器
let obj = {}let other = ''Object.defineProperty(obj, 'name', { enumerable: true, // 枚举 configurable: true, // 配置 get(){ // 读取方法 console.log('-----') // 这里可以处理逻辑 return other }, set(val){ // 设置方法 other = val }})obj.name = 'world' // -> setconsole.log(obj.name); // -> get// -----// world
复制代码
通过 set 和 get 方法,可以在其内部实现我们自己的逻辑,以达到拦截器的效果
let obj = { other: '123', get name(){ return this.other; }, set name(val){ this.other = val; }}obj.name = 456;console.log(obj.name); // 456
复制代码
这样也可以实现效果,虽然代码量少,但是并没有上面的直观
评论