企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 6.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对象和上面例子是等价的。 ### 6.1.1 属性类型 ECMA-262第5版在定义只有**内部才用的特性**(attribute)时,描述了**属性**(property)的各种特征。ECMA-262定义这些特性是为了实现JavaScript引擎用的,因此在JavaScript中**不能直接访问**它们。 ECMAScript中有两种属性:**数据属性**和**访问权属性** **1. 数据属性** 数据属性包含一个数据值的位置,在这个位置可以读取和写入值。 数据属性有4个描述特性的属性: | 属性 | 描述 | |---|---| | [[Configurable]] | 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。| | [[Enumerable]] | 表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。| | [[Writable]] | 表示能否修改属性的值,默认为true。| | [[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之外的特性,都会导致错误。类似规则也适用于configurable。 在调用Obejct.defineProperty()方法时,如果不指定,configurable、writable、enumerable特性的**默认值都为false**。 **2. 访问器属性** 访问器属性不包含数据值,它们包含一对getter和setter函数(非必需)。在读取访问器属性时,会调用getter函数,返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,它负责决定如何处理数据。 访问器属性: | 属性 | 描述 | |---|---| | [[Configurable]] | 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。比如直接在对象上定义的属性,它们的这个特性默认值为true。 | | [[Enumerable]] | 表示能否通过for-in循环返回属性。对于直接在对象上定义的值,默认为true。 | | [[Get]] | 在读取属性时调用的函数,默认为undefined | | [[Set]] | 在写入属性时调用的函数,默认为undefined | 访问器属性不能直接定义,也是要使用Object.defineProperty()方法来定义。 ~~~ var book = { _year:2004, edition:1 }; Object.defineProperty(book,’year’,{ get:function(){ return this._year; }, set:function(newValue){ if (newValue>2004) { this._year = newValue; this.edition += newValue-2004; } } }); book.year = 2005; alert(book.edition); //2 ~~~ 以上代码创建了一个book对象,并给它定义了两个默认属性:`_year和edition`。前面的下划线是一种常用的记号,用于表示**只能通过对象方法访问的属性**。在这个函数里,把year属性修改为2005会导致`_year`变成2005,而`edition`变为2。这是使用访问器属性的常见方式,即**设置一个属性的值会导致其他属性发生变化。** **3. 定义多个属性** ECMAScript 5提供的Object.defineProperties()方法可以通过描述符一次定义多个属性,这个方法接收两个对象参数,第一个对象是要添加和修改其属性的对象,第二个对象的属性与第一个对象要添加或修改的属性一一对应。 ~~~ var book = {}; Object.defineProperties(book,{ _year: { value:2004 }, edition:{ value:1 }, year:{ get:function(){ return this._year; }, set:function(newValue){ if (newValue>2004) { this._year = newValue; this.edition += newValue-2004; } } } }); ~~~ **4. 读取属性的特性** ECMAScript 5提供的`Object.getOwnPropertyDescriptor()`方法可以取得给定属性的描述符,它接受两个参数:属性所在的对象和要读取其描述符的属性名称,返回来的是一个对象,如果是访问器属性,这个对象的属性有configurable、enumerable、get和set;如果是数据属性,这个对象的属性有configurable、enumerable、writable和value。 ~~~ var descriptor = Object.getOwnpropertyDescriptor(book,’_year’); alert(descriptor.value) //2005 alert(descriptor.configurable) //false alert(descriptor.get) //undefined console.log(descriptor.enumerable); // false console.log(typeof descriptor.get); // "function" ~~~ 这个方法只能用于实例属性,要取得原型属性的描述符,必须直接在原型对象上调用这个方法。 在JavaScript中,可以针对任何对象--包括DOM和BOM对象,使用Object.getOwnPropertyDescriptor()方法。