一、Object.defineProperty() : 在一个对象上定义新属性或者修改现有属性,并返回这个对象。
语法:
Object.defineProperty(obj, prop, descriptor)
参数:
obj: 要在其上定义或修改属性的对象
props: 要定义或修改属性的名称
descriptor: 将被定义或修改的属性描述符
属性描述符
有两种主要形式:数据描述符和存取描述符
1、数据描述符和存取描述符均具有以下可选键值
- configurable 当且仅当该属性的值为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
- enumerable当且仅当该属性的enumerable为true时,该属性可枚举。默认为 false。
2、数据描述符同时具有以下可选键值
- value该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
- writable当且仅当该属性的writable为true时,value才能被赋值运算符(=、+=、-=、*=、/=、%=、…)改变。默认为 false。
3、存取描述符同时具有以下可选键值
- get 一个给属性提供 getter 的方法,默认值undefined,访问该属性时,该方法会被执行。
- set 一个给属性提供 setter 的方法,默认值undefined,属性值被修改时触发执行该方法,该方法接受唯一参数即该属性新的参数值。
描述符可同时具有的键值如下图(摘自MDN)所示:
如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
例子
var obj = new Object();
Object.defineProperty(obj, 'name', {
configurable: false,
writable: true,
enumerable: true,
value: '李明'
})
console.log(obj.name) //李明
二、Object.defineProperties() :在一个对象上定义一个或多个新属性或者修改现有属性,并返回这个对象。
语法:
Object.defineProperties(obj, props)
obj: 要在其上定义或修改属性的对象
props: 要定义或修改属性的名称
例子
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});
三、Object.getOwnPropertyDescriptor() : 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
语法:
Object.getOwnPropertyDescriptor(obj, prop)
obj:需要查找的目标对象
prop:目标对象内属性名称
例子
var o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
// configurable: true,
// enumerable: true,
// get: /*the getter function*/,
// set: undefined
// }
注:在es5中如果第一个参数不是对象会报错。但在ES2015中会把第一个不是对象的参数转为对象处理
Object.getOwnPropertyDescriptor('foo', 0);
// 类型错误: "foo" 不是一个对象 // ES5 code
Object.getOwnPropertyDescriptor('foo', 0);
// Object returned by ES2015 code: {
// configurable: false,
// enumerable: true,
// value: "f",
// writable: false
// }
四、Object.getOwnPropertyDescriptors() : 用来获取一个对象的所有自身属性的描述符。如果没有任何自身属性,则返回空对象。
语法:
Object.getOwnPropertyDescriptors(obj)
例子
var person = {
name: '张三',
age: 18
}
var desc = Object.getOwnPropertyDescriptors(person);
console.log(desc)
结果如下:
{
age:{
configurable: true
enumerable: true
value: 18
writable: true
},
name:{
configurable: true
enumerable: true
value: '张三'
writable: true
}
}
拓展示例:
例一:
var a = 1;
var d = Object.getOwnPropertyDescriptor(window, 'a');
console.log(d)
// {
// configurable: false,
// value: 1,
// writable: true,
// enumerable: true
// }
例二:
a=1;//a相当于window的一个属性, window.a
var d = Object.getOwnPropertyDescriptor(window, 'a');
console.log(d)
// {
// configurable: true, // 此时configurable属性值为true
// value: 1,
// writable: true,
// enumerable: true
// }
例三;
var b = {
name: 'bbb'
}
var d = Object.getOwnPropertyDescriptor(b, 'name');
console.log(d)
// {
// configurable: true
// writable: true,
// enumerable: true
// value: 'bbb'
// }
通过以上三个例子比较可得:使用 var,let定义的任何变量,其configurable属性值都为false,使用字面量定义的对象,该对象内部的属性的数据描述符属性都为true。
get和set实现简易的数据双向绑定
html代码:
<body>
<p>
input1=><input type="text" id="input1">
</p>
<p>
input2=>
<input type="text" id="input2">
</p>
<div>
我每次比input1的值加1=>
<span id="span"></span>
</div>
</body>
js代码:
var oInput1 = document.getElementById('input1');
var oInput2 = document.getElementById('input2');
var oSpan = document.getElementById('span');
var obj = {};
Object.defineProperties(obj, {
val1: {
configurable: true,
get: function() {
oInput1.value = 0;
oInput2.value = 0;
oSpan.innerHTML = 0;
return 0
},
set: function(newValue) {
oInput2.value = newValue;
oSpan.innerHTML = Number(newValue) ? Number(newValue) : 0
}
},
val2: {
configurable: true,
get: function() {
oInput1.value = 0;
oInput2.value = 0;
oSpan.innerHTML = 0;
return 0
},
set: function(newValue) {
oInput1.value = newValue;
oSpan.innerHTML = Number(newValue)+1;
}
}
})
oInput1.value = obj.val1;
oInput1.addEventListener('keyup', function() {
obj.val1 = oInput1.value;
}, false)
oInput2.addEventListener('keyup', function() {
obj.val2 = oInput2.value;
}, false)