ECMA-262把对象定义为:”无序属性的集合,属性可以包含基本值、对象或者函数“,说的通俗一点,你的女朋友就是一个对象,性别、年龄是她的属性,逛街买衣服是她的方法。
1.创建自定义对象最简单的方式就是创建一个Object实例,然后为它添加属性和方法
2.字面量创建的对象和上面new出来的实例一样,据有相同的属性和方法,这些属性
在创建的时候都带有一些特征的值,javascript通过这些特征值来定义他们的行为
ECMAScript中有两种属性值:数据属性和访问器属性
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述行为的特性
[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者
能否把属性修改为访问器属性,默认值为true
[[Enumerable]]:表示能否通过for-in循环返回的属性。比如前面直接在对象上定义的属性。默认值
为true
[[Writable]]:表示能否修改属性的值。比如前面直接在对象上定义的属性,是可以修改他们的值的。默认值为true
[[Value]]:包含这个属性的数据值。默认值为undefined,读取值的时候从这个位置读;写入属性值的时候,把新的值保存在这个位置。
var person = {
name:“卢本伟”
}
在这个对象中,创建了一个名为name的属性,它的值是"卢本伟",其余的三个属性值默认为true。
如果你想要修改默认的特性,必须使用ES5中的 Object.defineProperty() 这个方法。这个方法接受三个参数:属性所在的对象、属性的名字、和一个描述符对象,描述符对象的属性必须是Configurable、Enumerable、Writable和Value 中的一个或者多个,可以修改对应的特征值,比如下面这段代码
创建了一个name的属性,他的值是"卢本伟牛逼",设置了writable为false,代表这个属性是只读的,不能被修改,因此,即使后面修改值为”难受呀!马飞“,打印出来的name还是最初的值。如果在严格模式下,赋值操作将会导致抛出异常。类似的规则也适用与 [[Configurable]] (配置)属性
Configurable配置为false,表示不能从对象中删除。如果在严格模式下,同样会导致报错。而且一但把属性定义为不可配置,就再也不能配置回来了,而且连调用Object.defineProperty() 修改除了writable以外的特性,都会导致错误
简言之:可以调用Object.defineProperty() 方法修改同一个属性,但是把Configurable 特性设置为false了之后,它就不跟你玩了
在调用Object.defineProperty() 方法时,如果不指定,Configurable、Enumerable、Writable默认
为false,看清楚,这是调用Object.defineProperty() 方法的时候,不指定,才是默认为false。虽然大多数情况下你根本用不到这种方法,了解一下也是好的。
访问器不包含数据值,它们包含一堆getter和setter函数(不是必须的,可以省略),在读取访问器属性的值的时候,会调用getter函数,这个函数返回有效的值;写入的时候调用setter函数并传入新值。访问器属性同样也有4个特性,如下
[[Configurable]]:同上
[[Enumerable]]:同上
[[Get]]:在读取属性时调用的函数,默认值为undefined
[[Set]]:在设置属性时调用的函数,默认值为undefined
访问器属性不能像数据属性那样直接定义,必须通过Object.defineProperty() 来定义
以上代码创建了一个book对象,并给它定义两个默认的属性: _year 和 edition。_year 前面的下划线是常用的记号,用于表示只能通过对象方法访问的属性(你就是要通过 对象 . _year来访问也不是不行)。而访问器属性year则包含一个getter函数数和一个setter函数。getter函数返回year的值, setter 函数通过计算来确定正确的版本。因此,把year属性修改为2005会导致year变成2005,而edition变为2。这是使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化。再提一点,复习一下前面的东西
红色实线框里面的属性或者方法是不是颜色很浅?为什么?Object.defineProperty() 调用的时候,其余的属性不写的话默认是false, [[Enumerable]] 为false,表示该属性不能为for-in返回,所以颜色比较浅。你设置为true的话,year的颜色就变深了。
刚刚讲到哪里了?哦!对getter和setter,他们不一z定要同时指定,如果只制定getter意味着属性是只读的,如果在严格模式下写入会报错,同样只设置setter,读的话,只返回undefined
,严格模式下会报错。
写一个对象的时候,可能会定义很多属性,那么ES5定一个同时设置多个属性的方法Object.defineProperties() 这个方法接受两个对象参数:第一个是要添加和修改其属性的对象,第二个对象的属性要和第一个对象中要添加或修改的属性一一对应。
以上代码定义了两个数据属性(_year和edition)和一个访问器属性(year),与上一节定义的对象相同。只不过这里的属性是同一时间被创建的。
ES5中给出了Object.getOwnPropertyDescriptor() 方法,可以获取给定属性的描述符。这个方法接受两个参数:属性所在的对象,要读取其描述符的属性名称。返回值是一个对象
如果是访问器属性,这个对象的属性有configurable、enumerable、get和set
如果是数据属性,这个对象的属性有configurable、enumerable、writable和value
对于数据属性_ year, value等于最初的值, configurable是false,而get等于undefined.
对于访问器属性year, value 等于undefined, enumerable 是false, 而get是-一个指向getter
函数的指针。
来源:《高级程序设计》(第3版)