JS 属性描述符

属性描述符

1.概述

对象里目前存在的属性描述符有两种主要形式:

  • 数据描述符:是一个具有值的属性,该值可能是可写的,也可能不是可写的。

  • 存取描述符:是由getter-setter函数对描述的属性。

描述符必须是这两种形式之一;不能同时是两者。

2.可选键值

先来看看文档中的图片
在这里插入图片描述

2.1数据描述符的可选键值

从图中可以看到,只属于数据描述符的可选键值为 value 和 writable

value(默认值:undefined)

  • 代表该属性的值,可以是JS中任意有效类型的值(对象,数值,字符串等),包括Symbol类型

writable(默认:false)

  • 仅当该属性为true时,value才能被赋值运算符改变。
2.2存取描述符的可选键值

从图中可以看到,只属于存取描述符的可选键值为 get 和 set

get

  • 获取该属性时会触发的拦截行为。
    方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象),如果没有 getter 则为 undefined

set

  • 设置该属性时会触发的拦截行为。如果没有 setter 则为 undefined
2.3数据描述符和存取描述符共有的可选键值

configurable(默认值:false)

  • 只有当configurable 的值为 true 时。该属性的属性描述符才可以被改变(删除)。

enumerable(默认值:false)

  • enumerabletrue时,该属性为可枚举

3.使用属性描述符

目前有两种方法可以修改属性描述符
ES5.1 提供的 Object.defineProperty
ES6 提供的 Object.defineProperties

3.1.Object.defineProperty()

Object.defineProperty() 方法会直接在对象上定义一个新属性,或者修改一个对象的属性, 并返回这个对象。

三个参数Object.defineProperty(obj, prop, descriptor)

  • obj:目标对象
  • prop:要改变的属性
  • descriptor:要改变或定义的属性描述符

看一个例子,设置一个数据描述符

var obj = {}
	//设置一个数据描述符
	Object.defineProperty(obj,'define',{
	    value: 10, //定义值
		writable: true, //可写
		enumerable: true, //可被枚举
		configurable: true //可修改描述符
	})
	console.log(obj.define) // 10

上面代码用Object.defineProperty定义了一个属性以及它自身的属性描述符,又因为描述符的定义。
所以这个属性是可以被枚举被修改和删除的。

注意:如果configurable描述符为false ,之后再获取(定义)此属性的描述符会报错。

下面再来定义存取描述符

//写法一
var obj = {}
	//设置一个存取描述符
	Object.defineProperty(obj,'define',{
		get: () =>  console.log('get拦截成功') ,
		set: value => console.log('set拦截成功')
	})
obj.define  //get拦截成功
obj.define = 1 //set拦截成功,不会改变值

//写法二
var obj = {}
var descript = {
	get: () =>  console.log('get拦截成功') ,
	set: value => console.log('set拦截成功')
}
Object.defineProperty(obj,'define',descript)
  obj.define  //get拦截成功
  obj.define = 1 //set拦截成功,不会改变值

注意:定义的拦截操作,不涉及原型。除非将目标对象指向原型。
若目标对象指向对象原型,因为继承关系,当在对象上进行存取操作时(不管是不是原型),也会被拦截

如果目标对象指向原型,那么拦截操作的返回值会被所有继承该原型的对象共享
可以通过将值存储在另一个属性中解决。通过 this 指向某个被访问和修改属性的对象。

function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  get() {
    return this.stored_x;//this指向调用的目标对象,不会影响其他的实例
  },
  set(x) {
    this.stored_x = x; //this指向调用的目标对象,不会影响其他的实例
  }
});

var a = new myclass();
var b = new myclass();
//a 与 b 继承同一个原型
a.x = 1;
console.log(b.x); // undefined

由于 ES6 引入了 Symbol 数据类型,所以Object.defineProperty方法是定义keySymbol的属性的方法之一

3.2.Object.defineProperties()

bject.defineProperties()方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。 跟Object.defineProperty()`不同的是,该方法可以一次性操作多个属性

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  //.....
});

4.查询属性描述符

Object.ownPropertyDescriptor(object, property)
使用其方法,可以查询到属性描述符。不做赘述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值