Object.defineProperty()

Object.defineProperty()

语法

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

Object.defineProperty(obj, prop, descriptor)

  1. obj
    要定义属性的对象。
  2. prop
    要定义或修改的属性的名称
  3. descriptor
    要定义或修改的属性描述符。

规则

  1. 第一次进行赋值操作(a.b = xx or a[b] = xx or a = { b: xxx }),相当于使用 Object.defineProperty(a, ‘b’ ,{value: xxx, configurable: true, enumerable: true, writable: true})
  2. 首次使用 Object.defineProperty(a, ‘b’ ,{value: xxx}) 为对象添加一个值,等价于 Object.defineProperty(a, ‘b’ ,{value: xxx, configurable: false, enumerable: false, writable: false})
  3. 首次使用 Object.defineProperty 为对象添加一个值,之后再次使用 Object.defineProperty 修改对象属性的描述,只会修改本次配置中有的描述符,其它的描述符会继承本次修改前的描述符值,而不是修改为默认值
  4. configurable 为 false 时,configurable 不能变为 true
  5. configurable 为 false 时,不可以更改enumerable,true => false; false => true 都不可以
  6. configurable 为 false 时,writable 为 true ,可以更改value,否则不可以更改value
  7. configurable 为 false 时,可以更改 writable , true => false 可以, false => true 不可以
  8. configurable 为 true 时,configurable 可以变为false
  9. configurable 为 true 时,可以更改 enumerable ,true => false; false => true 都可以
  10. configurable 为 true 时,可以更改value
  11. configurable 为 true 时,可以更改 writable , true => false; false => true 都可以
  12. 赋值操作(a.b = xx or a[b] = xx)只有在 writable 为 true 时可以,无论 configurable 是否为true
  13. 修改 value 值的方式改变属性值,在 writable 为 true 或者 configurable 为 true 时都可以
  14. 当 configurable 为true时,可以从对应的对象上删除该属性
1. 第一次进行赋值操作(a.b = xx or a[b] = xx or a = { b: xxx }),相当于使用 Object.defineProperty(a, ‘b’ ,{value: xxx, configurable: true, enumerable: true, writable: true})

let a = {
	b: 1
};

Object.getOwnPropertyDescriptor(a, 'b'); // { value: 1, writable: true, enumerable: true, configurable: true }
2. 首次使用 Object.defineProperty(a, ‘b’ ,{value: xxx}) 为对象添加一个值,等价于 Object.defineProperty(a, ‘b’ ,{value: xxx, configurable: false, enumerable: false, writable: false})
let a = {};
Object.defineProperty(a, 'b', {
	value: 1
});
Object.getOwnPropertyDescriptor(a, 'b'); // { value: 1, writable: false, enumerable: false, configurable: false }
3. 首次使用 Object.defineProperty 为对象添加一个值,之后再次使用 Object.defineProperty 修改对象属性的描述,只会修改本次配置中有的描述符,其它的描述符会继承本次修改前的描述符值,而不是修改为默认值
let a = {};
Object.defineProperty(a, 'b', {
	value: 1, 
	writable: true, 
	enumerable: true, 
	configurable: true
});
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	value: 2
});
console.log(a.b); // 2

console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: 2, writable: true, enumerable: true, configurable: true}
4. configurable 为 false 时,configurable 不能变为 true
let a = {};
Object.defineProperty(a, 'b', {
	configurable: false
});

// Uncaught TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
	configurable: true
});
5. configurable 为 false 时,不可以更改 enumerable ,true => false; false => true 都不可以
let a = {};
Object.defineProperty(a, 'b', {
	configurable: false,
	enumerable: true
});

// Uncaught TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
	configurable: false,
	enumerable: false
});
let a = {};
Object.defineProperty(a, 'b', {
	configurable: false,
	enumerable: false
});

// Uncaught TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
	configurable: false,
	enumerable: true
});
6. configurable 为 false 时, writable 为 true ,可以更改value,否则不可以更改value
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	configurable: false,
	writable: true
});
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	value: 2
});
console.log(a.b); // 1
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	configurable: false,
	writable: false
});
console.log(a.b); // 1

// Uncaught TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
	value: 2
});
console.log(a.b);
7. configurable 为 false 时,可以更改 writable , true => false 可以, false => true 不可以
let a = {};
Object.defineProperty(a, 'b', {
	configurable: false,
	writable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: true, enumerable: false, configurable: false}

Object.defineProperty(a, 'b', {
	configurable: false,
	writable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: false}
let a = {};
Object.defineProperty(a, 'b', {
	configurable: false,
	writable: false
});

// Uncaught TypeError: Cannot redefine property: b
Object.defineProperty(a, 'b', {
	configurable: false,
	writable: true
});
8. configurable 为 true 时,configurable 可以变为false
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: true}

Object.defineProperty(a, 'b', {
	configurable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: false}
9. configurable 为 true 时,可以更改 enumerable ,true => false; false => true 都可以
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true,
	enumerable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: true, configurable: true}

Object.defineProperty(a, 'b', {
	configurable: true,
	enumerable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: true}
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true,
	enumerable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: true}

Object.defineProperty(a, 'b', {
	configurable: true,
	enumerable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: true, configurable: true}
10. configurable 为 true 时,可以更改value
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true,
	value: 1
});
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	configurable: true,
	value: 2
});
console.log(a.b); // 2
11. configurable 为 true 时,可以更改 writable , true => false; false => true 都可以
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true,
	writable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: true, enumerable: false, configurable: true}

Object.defineProperty(a, 'b', {
	configurable: true,
	writable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: true}
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true,
	writable: false
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: false, enumerable: false, configurable: true}

Object.defineProperty(a, 'b', {
	configurable: true,
	writable: true
});
console.log(Object.getOwnPropertyDescriptor(a, 'b')); // {value: undefined, writable: true, enumerable: false, configurable: true}
12. 赋值操作(a.b = xx or a[b] = xx)只有在 writable 为 true 时可以,无论 configurable 是否为true
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	writable: true,
	configurable: true
});
console.log(a.b); // 1

a.b = 2;
console.log(a.b); // 2

Object.defineProperty(a, 'b', {
	configurable: false
});
a.b = 3;
console.log(a.b); // 3
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	writable: false,
	configurable: true
});
console.log(a.b); // 1

a.b = 2;
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	configurable: false
});
a.b = 3;
console.log(a.b); // 1
'use strict'
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	writable: false,
	configurable: true
});
console.log(a.b); // 1

// Uncaught TypeError: Cannot assign to read only property 'b' of object '#<Object>'
a.b = 2;
13. 修改 value 值的方式改变属性值,在 writable 为 true 或者 configurable 为 true 时都可以
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	writable: true,
	configurable: false
});
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	value: 2
});
console.log(a.b); // 2
let a = {};
Object.defineProperty(a, 'b', {
	value: 1,
	writable: false,
	configurable: true
});
console.log(a.b); // 1

Object.defineProperty(a, 'b', {
	value: 2
});
console.log(a.b); // 2
14. 当 configurable 为true时,可以从对应的对象上删除该属性
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true
});

delete a.b // true

Object.defineProperty(a, 'c', {
	configurable: false
});
delete a.c // false
'use strict'
let a = {};
Object.defineProperty(a, 'b', {
	configurable: true
});

delete a.b // true

Object.defineProperty(a, 'c', {
	configurable: false
});
// VM1417:12 Uncaught TypeError: Cannot delete property 'c' of #<Object>
delete a.c

描述符可拥有的键值

configurableenumerablevaluewritablegetset
数据描述符可以可以可以可以不可以不可以
存取描述符可以可以不可以不可以可以可以

如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常。

let a = {};
// VM1535:2 Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
Object.defineProperty(a, 'b', {
	value: 1,
	set: () => {

	}
});

get & set

var obj = {
	//定义_x属性
    _x : 1,  
    //定义x属性的getter
    get x() { return this._x },  
    //定义x属性的setter
    set x(value) {  
        if (typeof value != "number") throw new Error('请输入数字');
        this._x = value;  //赋值
    }
};

console.log(obj.x);  // 1

obj.x = 2;
console.log(obj.x);  // 2

利用get&set实现双向数据绑定

<!DOCTYPE html>
<html>
<head>
	<title>defineProperty双向数据绑定</title>
</head>
<body>
	<p>
		输出测试数据: <input type="text" id="input" />
	</p>
	<p id="show-area">
		obj.val1值: {{obj.val1}}
	</p>
	<p>
		更改obj.val1: <input type="text" id="change-obj-val1" />
	</p>
</body>
<script type="text/javascript">
	const inputEle = document.getElementById('input');
	const obj = {};
	let objShowText = document.getElementById('show-area').innerText;

	function setValue(newValue) {
		inputEle.value = newValue;
		let innerText = document.getElementById('show-area').innerText;
		document.getElementById('show-area').innerText = objShowText.replace('{{obj.val1}}', newValue)

	}

	// 添加代理
	Object.defineProperty(obj, 'val1', {
		get: () => {

		},
		set: (newValue) => {
			// js 对象更改时更新页面
			setValue(newValue);
		}
	});

	// 监听页面输入,页面输入的话更新js对象
	inputEle.addEventListener('keyup', (event) => {
		obj.val1 = event.target.value;
	});


	// js对象更改同步页面显示
	document.getElementById('change-obj-val1').addEventListener('keyup', (event) => {
		obj.val1 = event.target.value;
	});

</script>
</html>

参考

Object.defineProperty()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值