js 之 Object.defineProperty()

一、前言

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象;
该方法也是vue实现数据绑定和更新数据的核心代码之一。

二、语法

Object.defineProperty(obj,prop,descriptor)
  • obj:要定义属性的对象;
  • prop:要定义或修改的属性名称;
  • descriptor:要定义或修改的属性描述符;

三、属性描述符

对象的属性描述符也是一个普通对象,主要有两种形式:数据描述符和存取描述符;

  • 数据描述符:具有值的属性和值是否可写的属性;
  • 存取描述符:具有 getter 函数和 setter 函数所描述的属性;

一个描述符只能是这两者其中之一;不能同时是两者

这两种描述符对象,共享以下两个键值(默认值是指在使用 Object.defineProperty() 定义属性时的默认值):

  • configurable
    当且仅当该键值为 true 时,该属性的描述符才能够被改变(即可以被重新定义),同时该属性也能从对应的对象上被删除。
    默认值:false。

例如:

var obj = {};
Object.defineProperty(obj,'fullName1',{
	configurable:false,
	value:1
})
Object.defineProperty(obj,'fullName2',{
	configurable:true,
	value:2
})
console.log(obj);  // {fullName1: 1, fullName2: 2}
delete obj.fullName1;
delete obj.fullName2;
console.log(obj);  // {fullName1: 1}    fullName1属性没有被删除,fullName2属性被删除了
  • enumerable
    当且仅当该键值为 true 时,该属性才会出现在对象的枚举属性中。
    默认值:false。

例如:

var obj = {};
Object.defineProperty(obj,'fullName1',{
		configurable:true,
		value:1,
		enumerable:false
	})
	Object.defineProperty(obj,'fullName2',{
		configurable:true,
		value:2,
		enumerable:true
	})
	console.log(Object.keys(obj))  // ['fullName2']  

数据描述符具有以下两个特有可选键值:

  • value
    该属性对应的值。
    默认值:undefined。
  • writable
    当且仅当该键值为 true 时,属性的值,也就是上面的 value,才能被改变。
    默认值:false。

例如:

var obj = {};
Object.defineProperty(obj,'fullName1',{
		configurable:true,
		value:1,
		enumerable:false,
		writable:false
	})
	Object.defineProperty(obj,'fullName2',{
		configurable:true,
		value:2,
		enumerable:true,
		writable:true
	})
	obj.fullName1 = 3;
	obj.fullName2 = 4;
	console.log(obj)   //  {fullName2: 4, fullName1: 1}
	// 只有fullName2被修改了

存取描述符具有以下两个特有可选键值:

  • get
    属性的 getter 函数,如果没有 getter,则为 undefined。**当访问该属性时,会调用此函数。**执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
    默认值:undefined。

例如:

var obj = {};
Object.defineProperty(obj,'firstName',{
	configurable:true,
	enumerable:true,
	value:'zhang'
})
Object.defineProperty(obj,'endName',{
	configurable:true,
	enumerable:true,
	value:'san'
})
Object.defineProperty(obj,'fullName',{
	configurable:true,
	enumerable:true,
	get(){
		return this.endName+'.' +this.firstName;  
	}
})
console.log(obj.fullName);  // san.zhang  当属性被访问时,才会调用函数
  • set
    属性的 setter 函数,如果没有 setter,则为 undefined。**当属性值被修改时,会调用此函数。**该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
    默认值:undefined。
    例如:

      var obj = {};
      Object.defineProperty(obj,'firstName',{
      	configurable:true,
      	enumerable:true,
      	value:'zhang',
      	writable:true,
      })
      Object.defineProperty(obj,'endName',{
      	configurable:true,
      	enumerable:true,
      	value:'san',
      	writable:true
      })
      Object.defineProperty(obj,'fullName',{
      	configurable:true,
      	enumerable:true,
      	get(){
      		return  this.endName+'.' +this.firstName; 
      	},
      	set(value){
      		let temp = value.split('.');
      		console.log(temp)
      		this.endName = temp[0];
      		this.firstName = temp[1];
      	}
      })
      console.log('firstName:'+obj.firstName,'endName:'+obj.endName,'fullName:'+obj.fullName);   // firstName:zhang endName:san fullName:san.zhang
      obj.fullName = 'si.li';
      console.log('firstName:'+obj.firstName,'endName:'+obj.endName,'fullName:'+obj.fullName);  // firstName:li endName:si fullName:si.li
    

如果一个描述符不具有 value、writable、get 和 set 中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常

注意:
这些选项不一定是自身属性,也要考虑继承来的属性。为了确保在设置前,保留这些默认值,可以明确指定所有的选项值,或者通过Object.create(null) 将 __ proto__ 指向null。

例如:

// 使用 __proto__
var obj = {};
var descriptor = Object.create(null); // 没有继承的属性
// 默认没有 enumerable,没有 configurable,没有 writable
descriptor.value = 'static';
Object.defineProperty(obj, 'key', descriptor);

// 显式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值