概述
最后更新于:2022-04-01 23:54:52
## 对象概述
面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript中并没有类的概念,所以它的对象也有有所不同。
ECMAScript对象是一个无序属性的集合,其属性可以包含基本值、对象或函数。
对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。
每个对象都是基于一个引用类型创建的。
**1、对象**
**1.1 创建对象**
(1)创建自定义对象的最简单方式就是创建一个Object的实例,然后给其添加属性和方法:
```
var person = new Object();
person.name = 'tg';
person.age = 10;
person.say = function(){
console.log(this.name);
}
```
上面的例子创建了一个名为person的对象,并为它添加了两个属性(name、age)和一个方法(say())。
(2)对象字面量
```
var person = {
name: 'tg',
age: 10,
say: function(){
console.log(this.name);
}
}
```
这个person对象和上面例子是等价的。
**1.2 属性类型**
ECMA-262第5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征。ECMA-262定义这些特性是为了实现JavaScript引擎用的,因此在JavaScript中不能直接访问它们。该规范将它们放在了两对方括号中,表示特性是内部值,如[[Enumerable]]。
ECMAScript中有两种属性:数据属性和访问权属性
**1.2.1 数据属性**
数据属性包含一个数据值的位置,在这个位置可以读取和写入值。
数据属性有4个描述特性:
- [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。
- [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。
- [[Writable]]:表示能否修改属性的值。
- [[Value]]: 包含这个属性的数据值。读取属性值时,从这个位置读;写入属性值时,把新值保存在这个位置。默认值为undefined。
要修改属性默认的特性,必须使用ECMAScript 5的`Object.defineProperty()`方法,这个方法接收三个参数:属性所在的对象、属性的名字和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable和value。
```
var person = {};
Object.defineProperty(person, 'name', {
writable: false,
value: 'tg'
});
console.log(person.name); // "tg"
person.name = 'tg2';
console.log(person.name); // "tg"
```
在上面的例子中,我们将person对象中的名为name的属性的`writable`设置为false,也就是不可修改,所以即使后面执行了person.name='tg2',最后person对象的name值依旧是原始值。
注意:在严格模式下,如果对一个不可修改的属性执行赋值操作,会抛出错误;非严格模式下则忽略赋值操作。
一旦将configurable特性设置为false后,就不能再把它变回可配置的了,如果再修改除writable之外的特性,都会导致错误。
**1.2.2 访问器属性**
访问器属性不包含数据值,它们包含一对getter和setter函数(非必需)。在读取访问器属性时,会调用getter函数,返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,它负责决定如何处理数据。
访问器属性:
- [[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。
- [[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。
- [[Get]]:在读取属性时调用的函数,默认为undefined
- [[Set]]:在写入属性时调用的函数,默认为undefined
访问器属性不能直接定义,也是要使用`Object.defineProperty()`方法来定义。
```
var person = {
_age: 20,
intro: ''
};
Object.defineProperty(person, 'age', {
get: function() {
return this._age;
},
set: function(newValue){
if(newValue < 18) {
this.intro = '装嫩';
this._age = newValue;
}
}
});
console.log(person.age); // 20
person.age = 17;
console.log(person.intro); // "装嫩"
```
在上面的例子中,访问器属性age有一个getter函数和一个setter函数。getter函数返回`_age`的值,setter函数通过判断`age`的设置值来改变其他属性值。
**1.2.3 定义多个属性**
ECMAScript 5提供的`Object.defineProperties()`方法可以通过描述符一次定义多个属性,这个方法接收两个对象参数,第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象要添加或修改的属性一一对应。
```
var person = {};
Object.defineProperties(person, {
_age: {
value: 20
},
intro: {
value: ''
},
age: {
get: function(){
return this._age;
},
set: function(newValue){
if(newValue < 18) {
this.intro = '装嫩';
this._age = newValue;
}
}
}
});
```
**1.2.4 读取属性的特性**
ECMAScript 5提供的`Object.getOwnPropertyDescriptor()`方法可以取得给定属性的描述符,它接受两个参数:属性所在的对象和要读取其描述符的属性名称,返回来的是一个对象,如果是访问器属性,这个对象的属性有configurable、enumerable、get和set;如果是数据属性,这个对象的属性有configurable、enumerable、writable和value。
```
var person = {
_age: 20,
intro: ''
};
Object.defineProperty(person, 'age', {
get: function() {
return this._age;
},
set: function(newValue){
if(newValue < 18) {
this.intro = '装嫩';
this._age = newValue;
}
}
});
var descriptor = Object.getOwnPropertyDescriptor(person,'age');
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // "function"
```
在JavaScript中,可以针对任何对象--包括DOM和BOM对象,使用`Object.getOwnPropertyDescriptor()`方法。
';