Object.defineProperty()详解

前言:
JavaScript 对象与其他面向对象的语言( 如Java )不太一样,因为ES6 之前没有类的概念。幸运的是,ES6TypeScript 都引入了类的概念,这就使我们理解和使用起来更为方便。 在学习js对象之前,先把一些重要概念走一遍,有助于我们更好地理解对象,第一个要掌握的就是 Object.defineProperty()


属性特性(属性描述符)

【属性特性】 是用来描述js对象的属性的一些内在特征,如这些属性是否可写,是否可枚举,是否可配置等。属性特性分为两类,分别为数据属性访问器属性(也叫存取器属性)。

1.数据属性

configurable [Boolean]表示能否通过delete删除属性,能否修改属性的特性,能否把属性修改为访问器属性
enumerable [Boolean]表示是否能通过 for-in 枚举该属性
writable [Boolean]表示能否修改属性的值
value [any]表示这个属性的值

要想设置属性的特性,或者想让新建属性具有某种特性,则必须使用ES5中定义的Object.defineProperty(obj,property,descriptor)

obj [Object]表示传入的要修改的对象
property [String]表示该对象需要修改或新建的属性
descriptor [Object]表示该属性对应的属性特性

举例:

var person = { name: "Tom" , age: 24 }
Object.defineProperty(person,"name",{  //修改name的属性特性
	enumerable:false,   //设置为不可枚举
	writable: false,     //设置为只读属性
	configurable: false,  //设置为不可配置
	value: "Jerry"      //设置属性值 
})
// 1.验证enumerable
for(var property in person){
	console.log(property)        // age 
}
// 2.验证writable
console.log(person.name)    //Jerry
person.name = "Helen"
console.log(person.name)   //Jerry,(严格模式:throw Error)
// 3.验证configurable
delete person.name // 属性还在,什么也不发生  (严格模式:throw Error)

划重点:
(1)关于configurable,一旦将属性定义为不可配置的,就不能再把它变为可配置了

举例:

var person = { name: "Tom" , age: 24 }
Object.defineProperty(person,"name",{ 
	configurable: false,  //设置为不可配置
})
// throw Error
Object.defineProperty(person,"name",{ 
	configurable: true,  //设置为可配置,报错
})

划重点
(2)在调用Object.defineProperty()方法创建一个新的属性时,如果不指定属性特性,则enumerable,writable,configurable均默认为false。如果调用Object.defineProperty()方法只是修改已定义的属性时,则以上三个特性默认为true。

举例:

//通过Object.getOwnPropertyDescriptor()方法可以拿到属性a的属性描述符

var obj1 = {}
Object.defineProperty(obj1 ,"num",{})
Object.getOwnPropertyDescriptor(obj1,"num")  // {value: undefined, writable: false, enumerable: false, configurable: false}

var obj2 = { num :10 }
Object.defineProperty(obj2 ,"num",{})
Object.getOwnPropertyDescriptor(obj2,"num")  // {value: 10, writable: true, enumerable: true, configurable: true}

2.访问器属性

configurable [Boolean]同数据属性,不同之处:能否把属性修改为数据属性
enumerable [Boolean]同数据属性
get [Function]读取属性值的时候触发这个方法
set [Function]写入属性值的时候触发这个方法

不同于数据属性,访问器属性不能直接定义,必须通过Object.defineProperty()来定义

举例:

// 通过访问器属性改变总冠军队伍
var winner = { team : 'unknown' }
Object.defineProperty(winner,'num',{
    get: function(){
        return this.team
    },
    set:function(num){
        if(num === 1){
            this.team = 'Warriors'
        }else{
            this.team = 'Rockets'
        }
    }
})

//以下是使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化
console.log(winner.team)   //unknown
winner.num = 1
console.log(winner.team)  //Warriors
winner.num = 2
console.log(winner.team)  //Rockets

3.总结(个人见解)

对比以上两种属性特性,访问器属性的用途会更广一些。例如现在最流行的前端框架Vue,其源码中使用了Object.defineProperty()来定义访问器属性,通过观察者模式监听数据变化,从而实现双向数据绑定。
Object.defineProperty()我们使用的机会并不多,很多框架源码中,或者ES6中的修饰器(Decorator)原理都是通过以上方法改造的

如有不恰当的地方,欢迎多多批评指正 ^ _ ^

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Object.defineProperty是一个用来在一个对象定义属性或者修改已存在属性的方法。[2]它可以通过设置属性的描述符来控制属性的行为,包括属性的可枚举性、可配置性、可写性以及属性的值等。通过使用Object.defineProperty,我们可以实现对对象属性的监听和控制,从而实现双向数据绑定。 举个简单的例子,假设我们有一个名为person的对象,其中包含name和age两个属性,我们可以通过使用Object.defineProperty来添加一个新的属性sex,并设置它的值为男。代码如下: let person = { name:"码农", age: 18 } Object.defineProperty(person,'sex',{ value:"男" }) console.log(person) 运行以上代码,我们可以在控制台中看到person对象中已经添加了一个名为sex的属性,其值为男。这就是Object.defineProperty的基本用法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue源码学习之Object.defineProperty对象属性监听](https://download.csdn.net/download/weixin_38663151/14904644)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Object.defineproperty方法(详解)](https://blog.csdn.net/weixin_57677300/article/details/126278467)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值