JavaScript中对象的属性类型

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

JavaScript中对象的属性类型
JavaScript中,对象的属性有两种:数据属性和访问器属性。

数据属性
特性:
数据属性包括⼀个数据值的位置。

在这个位置可以读取和写⼊值。

数据属性有4个特性。

[[configurable]]:可配置。

表⽰能否删除属性、能否修改属性的特性、能否把属性变为访问器属性。

[[enumerable]]:可枚举。

表⽰能否通过for-in循环进⾏遍历。

[[writable]]:可写。

表⽰能否修改属性的值。

[[value]]:表⽰这个属性的数据值。

设置:
ES5提供了Object.defineProperty()⽅法,来设置属性的默认特性。

该⽅法接收三个参数:属性所在对象、属性名字、属性描述符对象。

其中,描述符对象⽤来设置configurable、enumerable、writable、value中的⼀个或多个值。

ES5也提供了Object.defineProperties⽅法,可以定义多个属性。

在设置了属性的特性后,任何尝试超过configurable或writable权限的操作,在⾮严格模式下将会被忽略,在严格模式下将会抛出错误。

⼀旦把属性定义为configurable: false,就不能再变回configurable: true了。

否则,⽆论是否处于严格模式,都会抛出TypeError错误。

例外:即便属性是foncigurable: false,仍然可以把writable的状态由true改为false,但是⽆法由false改为true。

var person = {};
Object.defineProperty(person, 'name', {
configurable: false,
writable: false,
value: 'Nicholas'
});
// 测试:删除属性
delete ; // 由于configurable: false,删除失败
console.log(); // Nicholas
// 测试:修改特性
Object.defineProperty(person, 'name', {
configurable: true
}); // 抛出错误:TypeError: Cannot redefine property: name
// 测试:修改属性的值
= 'Greg'; // 由于writable: false,修改失败
console.log(); // Nicholas
结合configurable: false和writable: false,就可以创建⼀个真正的常量属性。

Object.seal()⽅法,会在⼀个现有对象上调⽤Object.preventExtensions(),并把所有属性标记为configurable: false。

Object.freeze()⽅法,会在⼀个现有对象上调⽤Object.seal(),并把所有属性标记为writable: false。

读取:
ES5提供了Object.getOwnPropertyDescriptor()⽅法,来取得给定属性的描述符。

该⽅法接收两个参数:属性所在对象、属性名字。

返回值是⼀个对象,其属性有configurable、enumerable、writable、value。

还有⼀种区分枚举属性enumerable的⽅法是propertyIsEnumerable()。

该⽅法不检查原型链。

在调⽤Object.defineProperty()⽅法时,如果不指定,configurable、enumerable、writable的默认值为false。

对于直接定义在对象上的属性,configurable、enumerable、writable的默认值为true,value的值为undefined。

// 使⽤Object.definedProperty设置的属性
var descriptor = Object.getOwnPropertyDescriptor(person, 'name');
console.log(descriptor.configurable); // false
console.log(descriptor.enumerable); // false
console.log(descriptor.writable); // false
console.log(descriptor.value); // Nicholas
// 直接定义在对象上的属性
var person2 = { name: "Greg" };
var descriptor2 = Object.getOwnPropertyDescriptor(person2, 'name');
console.log(descriptor2.configurable); // true
console.log(descriptor2.enumerable); // true
console.log(descriptor2.writable); // true
console.log(descriptor2.value); // Greg
// propertyIsEnumerable()⽅法
console.log(person.propertyIsEnumerable('name')); // false
console.log(person2.propertyIsEnumerable('name')); // true
关于可枚举属性
Object.keys(obj)会返回⼀个数组,包含所有可枚举属性。

不检查原型链。

Object.getOwnPropertyNames(obj)会返回⼀个数组,包含所有属性,⽆论是否枚举。

不检查原型链。

prop in obj会返回⼀个布尔值,判断对象的属性是否存在,⽆论是否枚举。

检查原型链。

obj.hasOwnProperty(prop)会返回⼀个布尔值,判断对象的指定属性是否存在,⽆论是否枚举。

不会检查原型链。

不可枚举的属性,不会出现在for-in循环的遍历中。

var myObject = {};
Object.defineProperty(myObject, 'a', {
enumerable: true,
value: 2
});
Object.defineProperty(myObject, 'b', {
enumerable: false,
value: 3
});
// propertyIsEnumerable
console.log(myObject.propertyIsEnumerable('a')); // true
console.log(myObject.propertyIsEnumerable('b')); // false
// Object.keys()
console.log(Object.keys(myObject)); // ["a"]
// Object.getOwnPropertyNames()
Object.getOwnPropertyNames(myObject); // ["a", "b"]
// in操作符
console.log('a' in myObject); // true
console.log('b' in myObject); // true
console.log('toString' in myObject); // true
// hasOwnProperty()
console.log(myObject.hasOwnProperty('a')); // true
console.log(myObject.hasOwnProperty('b')); // true
console.log(myObject.hasOwnProperty('toString')); // false
// 遍历
for (var k in myObject) {
console.log( k, myObject[k] );
} // a 2
访问器属性
特性:
访问器属性有4个特性。

对于访问器属性,JavaScript会忽略它们的writable和value特性,取⽽代之的该关⼼get和set属性。

[[configurable]]:表⽰能否删除属性、能否修改属性的特性、能否把属性变为访问器属性。

[[enumerable]]:表⽰能否通过for-in循环进⾏遍历。

直接定义在对象上的属性,默认值为true。

[[get]]:读取属性时调⽤的函数。

直接定义在对象上的属性,默认值为undefined。

[[set]]:写⼊属性时调⽤的函数。

直接定义在对象上的属性,默认值为undefined。

设置:
同样使⽤Object.defineProperty()⽅法和Object.defineProperties⽅法设置访问其属性。

不⼀定⾮要同时指定getter和setter函数。

只指定getter函数意味着属性不能写。

尝试写⼊属性,在⾮严格模式下将会被忽略,在严格模式下将会抛出错误。

只指定setter函数意味着属性不能读。

尝试读取属性,在⾮严格模式下将会返回undefined,在严格模式下将会抛出错误。

var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book, 'year', {
get: function() {
return this._year;
},
set: function(newYear) {
if (newYear > 2004) {
this._year = newYear;
this.edition += (newYear - 2004);
}
}
});
// 测试
book.year = 2005; // 注意:defineProperty中定义的属性名为year,⽽⾮_year
console.log(book.edition); // 2
另⼀种设置getter和setter函数的⽅法如下:
var myObject = {
// 定义getter
get foo() {
return 'You get: ' + this._foo_;
},
// 定义setter
set foo(val) {
this._foo_ = val;
}
}
// 测试
myObject.foo = 2;
console.log(myObject.foo); // You get: 2
读取:
同样使⽤Object.getOwnPropertyDescriptor()⽅法取得给定属性的描述符。

在调⽤Object.defineProperty()⽅法时,如果不指定,configurable、enumerable的默认值为false,get、set的默认值为undefined。

对于直接定义在对象上的属性,configurable、enumerable的默认值为true。

// 使⽤Object.definedProperty设置的属性
var descriptor = Object.getOwnPropertyDescriptor(book, 'year');
console.log(descriptor.configurable); // false
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // function
console.log(typeof descriptor.set); // function
// 直接定义在对象上的属性
var descriptor = Object.getOwnPropertyDescriptor(myObject, 'foo');
console.log(descriptor.configurable); // true
console.log(descriptor.enumerable); // true
console.log(typeof descriptor.get); // function
console.log(typeof descriptor.set); // function
参考:《JavaScript⾼级程序设计》、《你不知道的JavaScript(上卷)》。

相关文档
最新文档