Object.defineProperty() 详细解析

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。这个方法有三个参数,分别是对象,对象的属性值(key)和属性描述符,如果开始该对象没有这个属性值,就会就会定义一个新属性,如果开始就有,就是修改。

let obj = { a:1 }
Object.definePropety(obj,'a',{  //修改
	value:10,
})
Object.definePropety(obj,'b',{  //新建属性
	value:20
})
console.log(obj)    // {a:10,b:20}

属性描述符有两种类型:数据描述符和存取描述符,这两者有两个相同的属性和两个特有的属性。
数据描述符拥有以下属性:

key作用可选值默认值
value属性对应的值任意值都可以undefined
writable控制该属性是否能被=赋值true或falsefalse
enumerable控制该属性是否出现在对象的枚举属性中true或falsefalse
configurable控制该属性的除 value 和 writable 特性外的其他特性是否可以被修改和该属性能否被删除true或falsefalse

存取描述符拥有有以下属性:

key作用可选值默认值
enumerable控制该属性是否出现在对象的枚举属性中true或falsefalse
configurable控制该属性的除 value 和 writable 特性外的其他特性是否可以被修改和该属性能否被删除true或falsefalse
get属性的 getter 函数,当访问该属性时,会调用此函数functionundefined
set属性的 setter 函数,当属性值被修改时,会调用此函数functionundefined

各属性介绍
1.value属性:给该属性赋的值

let obj = {}
Object.defineProperty(obj,'a',{
	value:10
})
console.log(obj)  //{a:10}

2.writable 属性:控制该属性是否能被 “=” 赋值:

// 'use strict'
let obj = {};
Object.defineProperty(obj,"a",{
	value:11,
	writable:false,
})
console.log(obj.a);  // 11
obj.a = 20;
console.log(obj.a)  // 11

在普通模式下,给writable为false的属性使用赋值不会改变该属性,也不会报错,在严格模式下(‘use strict’),会报以下的错误:
在严格模式下给writable为false的值赋值
注意:就算writable为false,你依然可以通过Object.defineProperty()方法给该属性赋值。代码如下

let obj = {};
Object.defineProperty(obj,"a",{
	value:11,
	writable:false,
})
console.log(obj.a);  // 11
Object.defineProperty(obj,'a',{
	value:20
})
console.log(obj.a)  // 20

3.enumerable 属性:控制该属性是否能被枚举(for…in循环、Object.keys()等能否获取到该值),如果时false,就拿不到该属性

let obj = {a:1,b:2}
Object.defineProperty(obj,'c',{
	value:3,
	enumerable:false
})
console.log(obj.c)  // 3
console.log(Object.keys(obj)) // ["a","b"]

4.configurable 属性:表示对象的属性是否可以被删除,以及除 value 和 writable 属性外的其他属性是否可以被修改。
下面是对能否删除的测试

// 'use strict'
let obj = {};
Object.defineProperty(obj,'a',{
	value:10,
	configurable:false
})
delete obj.a
console.log(obj.a)  // 10,delete没有成功,但也不会报错,如果使用严格模式('use strict'),就会报错

下面是对能否修改属性测试

"use strict"
 let obj = {a:1,b:2}
 Object.defineProperty(obj,'c',{
 	value:3,
    enumerable:false,
    configurable:false
 })
 Object.defineProperty(obj,'c',{
   enumerable:true     // 会报错:Uncaught TypeError: Cannot redefine property: c
 })
 Object.defineProperty(obj,'c',{
   configurable:true   // 会报错:Uncaught TypeError: Cannot redefine property: c
 })

注意: 当 configurable 设置为 false 时,无法再次修改 configurable 的值,即一旦将该值设置为false,就无法再修改为true;

5.set 方法和set方法,就是对象的自定义 getters 和 setters ;在给对象的改属性赋值时,就会执行你写的set函数里面的代码,当你获取改属性时,获取到的就是你get函数里面的返回值;这两个一般会同时出现,如果只有get,没有set,那么改属性无法被改变,严格模式下还会报错;如果只有set,没有get,那么无法获取到改属性值(一直为 undefined );

let obj = {};
let arr = [];
Object.defineProperty(obj,'a',{
	set(val){
		arr.push(val)
	},
	get(){
		return arr
	}
})
obj.a = 1;
console.log(obj.a)  // [1]
obj.a = 2
console.log(obj.a)  // [1,2]

如以上例子,此时给obj的a属性赋值时,就不是覆盖掉之前 a 的值,而是将数据放在一个数组里,获取值的时候也是获取的一个数组;

**注意:**这里set和get函数不能通过 **this.**的形式对自己进行操作,因为对自己赋值时又会执行set和get函数,这样就无限调用,会报 Maximum call stack size exceeded 的错,如以下代码:

let obj = {};
Object.defineProperty(obj,'a',{
	set(val){
		this.a = val
	},
	get(){
		return this.a
	}
})

就会报下面这个错
错误
所以,设置值的时候需要使用另外一个变量或者对象的另外一个属性。

常用操作的默认值
1.在对象进行操作时,我们一般会进行如下操作:

let obj = {};
obj.a = 1

这个操作就相当于进行如下操作:

let obj = {}
Object.defineProperty(obj, "a", {
  value : 1,
  writable : true,
  enumerable : true,
  configurable : true
});

2.在使用Object.defineProperty()给属性赋值时,如果只传了value,如下:

let obj = {};
Object.defineProperty(obj,'a',{
	value:1
})

此时就相当于进行如下操作:

let Object.defineProperty(obj,'a',{
	value:1,
	writable:false,
	enumerable:false,
	configurable:false
})

此时对象的值是只读的,所以使用Object.defineProperty() 给属性赋值的时候不能偷懒,一般还是用第一种方法舒服 \(^o^)/ ,Object.defineProperty() 方法一般用于对该属性赋值时使用set和get进行自己相应的操作。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值