- ECMA-262在第五版定义了只有内部才用的特性(attribute)来描述属性(property)的各种特性。
- ECMA-262定义这些特性是为了实现Javascript引擎用的, 因此在Javascript中不能直接访问他们
- 为了表示特性是内部值,将它们放在两对方括号内,例如:
[[Prototype]]
- 有俩种属性:数据属性和访问器属性
数据属性
数据属性包含一个数据值的位置
[[ configurable ]]: 表示能否通过 delete 删除属性然后重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
[[ enumerable ]]: 表示能否通过 for-in 循环返回属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
[[ writable ]]: 表示能否修改属性的值。直接在对象上定义的属性,它们这个特性的默认值为 true;
[[ value ]]: 包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性的时候,把新值保存在这个位置。这个特性的默认值为 undefined ;
7224081-ad5a2ce940f1d308.png
要修改属性的特性,必须使用 ES5 的 Object.definePrototype()
方法。这个方法接受三个参数:
1、属性所在的对象。
2、属性的名字。
3、描述符对象。属性必须是:configurable
、enumerable
、writable
、value
中的一个或多个。
var obj = {};
Object.defineProperty(obj, 'name', {
writable: false, // 不能修改值
value: '张三'
})
console.log(obj.name); // 张三
obj.name = '李四';
console.log(obj.name); // 张三, writable设为 false 后,值就没法修改了。
var person = {
name: '李四',
age: 24
}
delete person.name;
console.log(person); // {age: 24}
Object.defineProperty(person, 'age', {
configurable: false
})
delete person.age;
console.log(person);// {age: 24} configurable特性设为 false 后,就没法使用 delete 删除了。
- 把 configurable 设置为 false 后,就不能用 delete 删除属性,而且,也不能修改 除 writable 外的特性。
var obj = {};
Object.defineProperty(obj, "name", {
configurable: false,
value: '张三'
})
// 会抛出错误
Object.defineProperty(obj, "name", {
configurable: true,
value: '张三'
})
image.png
也就是说,可以多次调用 Object.defineProperty()
方法修改同一个属性,但在把 configurable
特性设置为 false 后就有限制了。
在调用Object.defineProperty()
方法创建一个新的属性时,如果不指定,configurable
、enumerable
、writable
特性的默认值都是 false,如果是修改已存在的属性,就不会有这个限制。
访问器属性
访问器属性没有数据值,有get
、 set
函数。读取访问器属性时,会调用 get
函数,在写入值时会调用set
函数
访问器属性有如下四个特性:
[[ configurable ]]: 表示能否通过 delete 删除属性,从而重新定义属性。能否修改属性的特性,或者能否把属性修改为数据属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
[[ enumerable ]]: 表示能否通过 for-in 循环返回属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
[[ get ]]: 读取属性时,调用的函数。默认值为 undefined;
[[ set ]]: 写入属性时,调用的函数。默认值为 undefined;
访问器属性不能直接定义,必须通过Object.defintProperty()
来定义。
"use strict"
let person = {
name: '张三',
age: 25
}
Object.defineProperty(person, 'oldAge', {
get: function () {
return this.age + 1;
},
set: function (newValue) {
if (newValue > this.age) {
this.age = newValue - 1;
this.name = '李四'
} else {
this.age = newValue + 1;
this.name = "王五"
}
}
})
person.oldAge = 28;
console.log(person); // {name: '李四', age: 27};
//还有种古老的方式
let person = {
name: '张三',
age: 25
}
person.__defineGetter__('oldAge',function(){
return return this.age + 1;
});
person.__defineSetter__('oldAge',function(newValue){
if (newValue > this.age) {
this.age = newValue - 1;
this.name = '李四'
} else {
this.age = newValue + 1;
this.name = "王五"
}
});
age.year = 2017;
age.nowAge;
>>>21
上面定义了一个 person 对象。默认有两个属性, "name"、"age"。新增了一个访问器属性 "oldAge"。它包含了两个函数。
get 函数用来返回值。set函数,当为 "oldAge"写入值的时候,会调用。把 oldAge 设置为 27 后,调用 set 函数,改变了 person 对象的 "name" 和 "age" 属性值。
不一定非要同时指定 set、get函数。只指定 get函数,意味着属性不能写,严格模式会报错。只指定了set函数,属性就不能读取,严格模式同样会报错。
image.png image.png
定义多个属性
ES5 定义了一个 Object.defineProperties()
方法,可以通过描述符一次定义多个属性。这个方法,接受两个对象参数:第一个是要添加和修改其属性的对象,第二个就是要设置的属性的对象。
let car = {};
Object.defineProperties(car, {
createYear: {
writable: false,
value: 2010
},
color: {
writable: true,
value: 'block'
},
severalYear: {
get: function () {
return parseInt(new Date().getFullYear()) - this.createYear
},
set: function (newValue) {
if (newValue > 2010) {
this.color = 'red';
}
}
}
})
console.log(car.createYear); // 2010
console.log(car.color); // 'block'
console.log(car.severalYear); // 9
car.severalYear = 2015;
console.log(car.createYear); // 2010
console.log(car.color); // 'red'
console.log(car.severalYear); // 9
读取属性的特性
使用 ES5 的 Object.getOwnPropertyDescriptor()
方法,可以取得给定属性的描述符。这个方法接受两个参数:
1、属性所在的对象。
2、属性名称。
返回值是一个对象,如果是数据属性,这个对象的属性有:configurable
、enumerable
、writable
、value
。
如果是一个访问器属性,对象的属性有:configurable
、enumerable
、get
、set
。
let car = {};
Object.defineProperties(car, {
createYear: {
writable: false,
value: 2010
},
color: {
writable: true,
value: 'block'
},
severalYear: {
get: function () {
return parseInt(new Date().getFullYear()) - this.createYear
},
set: function (newValue) {
if (newValue > 2010) {
this.color = 'red';
}
}
}
})
let descriptpor = Object.getOwnPropertyDescriptor(car, "createYear");
console.log(descriptpor);
// { value: 2010,
// writable: false,
// enumerable: false,
// configurable: false }
let fangdescriptpor = Object.getOwnPropertyDescriptor(car, "severalYear");
console.log(fangdescriptpor); // 看下图
image.png
网友评论