此次咱们好好聊一聊对象这个东西,本次说的不是array
,也不是function
,而是object
对象是一种特殊的数据类型,这种数据类型还有其余的不少叫法,好比“散列”,“散列表”,“字典”,“关联数组”。javascript
对象按照建立者的角度,能够分为三类:内置对象
:是由javascript语言自己自定义的对象,大多数是一些预约好的构造函数类,好比Array
,Date
,Function
宿主对象
:是指javascript解释器所嵌入的宿主环境定义的对象,好比HTMLElement就是宿主对象。自定义对象
:是指由开发者在代码中所建立的对象。java
咱们知道对象的表达方式是:'属性':'值'api
属性按照来源不一样,能够分为两类:自有属性
:是指直接在对象中定义的属性。继承属性
:是指在对象原型链中的属性。数组
与此同时,对象的属性还具备一些特性:可写
:表明是否能够设置该对象所对应的该属性的值。可枚举
:表明是否能够经过api枚举出该属性。可配置
:表明是否能够删除或修改该属性。函数
记住上述概念,有助于咱们进行下一步的理解。this
建立对象有三种方式:
第一种:对象直接量spa
var o = {} var obj = { a: 1, 'b': 2, 'min title': 3 }
第二种:经过new建立对象code
var o = new Object()
第三种:Object.create()
该方法支持传入两个参数,第一个参数是对象的原型(就是所建立出的对象的_proto_
的指向),第二个参数是对属性进一步的描述(该参数可选,参数内容会在后面详解)对象
如下三种方式是等价的:blog
检测对象原型的方法除了instanceof
以外,还有一个isPrototypeOf()
,咱们来看一下使用:
咱们首先再明确一个概念:
咱们常见的{a: 1}
中的a
叫作数据属性
,除此以外还有一个叫作存取器属性
,存取器属性的值的读取和设置,都是由getter和setter控制的。
var o = { p: 0, set q(value) { this.p = value }, get q() { return this.p+=100 } } o.q = 1 console.log(o.q) // => 101 console.log(o.q) // => 201
其中,对象中的函数定义没有使用function
关键字,使用的而是get
和set关键字
处理能够这样定义存取器属性,咱们还能够利用其余的方法定义存取器属性
,就是咱们熟知的Object.defineProperty()
和Object.definePeoperties()
首先,咱们介绍一下Object.defineProperty()
定义数据属性
的方式
var o = {} // 定义属性 Object.defineProperty( o, 'x', { value: 1, writable: true, enumerable: true, configurable: true } ) // 修改属性 Object.defineProperty( o, 'x', { value: 2, writable: false } )
这个函数共有三个参数:
第一个参数是,须要加属性的对象。
第二个参数是,添加的属性的名称。
第三个参数是定义的配置项:
第一个配置就是这个属性所对应的值。
剩余三个配置就是对应到文章一开始所提到属性三个特性可写
,可枚举
,可配置
。
这四个配置项都不是必须填写。假如对于新建立的属性,value不填,默认值就是undefined
,其余配置项的缺省值是false
。假如对于修改已有的属性来讲,不填写的配置项就不作修改。
咱们再看一下Object.defineProperty()
定义存取器属性
的方式
其中,须要注意的是,在定义存取器属性
时没法定义,value
和writable
配置项,由于定义的get
和set
从某种意义上代替了前两个配置项。
var o = {y: 1} Object.defineProperty( o, 'x', { set(value) { this.y = value }, get() { return this.y+=100 }, enumerable: true, configurable: true } )
Object.defineProperty
只能单个定义或修改对象属性,Object.defineProperties
提供了批量解决的办法,以下:
var o = {} Object.defineProperties( o, { x: { set(value) { this.y = value }, get() { return this.y+=100 }, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: true, configurable: true } } )
Object.defineProperty
和Object.defineProperties
对于属性的修改是有规则和要求的,以下:
在这里,咱们再看一下上面的Object.create
方法,Object.create
的第二个参数是和Object.defineProperties
第二个参数同样的,缺省值一样为undefined
和false
没有提供选项去配置属性特性的方法,这些属性默认都是true,例如:new
关键字和对象直接量的方式建立对象,以及最上面对象直接量的方式设置getter和setter
对象的扩展性是什么,其实就是指对象可否添加新的属性,默认状况下全部的内置对象和自定义对象都是可扩展的。除非咱们人为的改变它:
Object.preventExtesions()
能够传入一个参数,就是你要取消扩展功能的对象,操做后,这个对象会不能扩展(即不能添加新属性),且不能恢复,操做只影响该对象自己,不对其余原型链操做产生影响。
咱们能够利用Object.esExtensible()
判断这个对象是否可扩展,传入一个对象,返回布尔值。
Object.seal()
能够将对象封闭,效果和上面的Object.preventExtesions()
同样,增长的效果是将这个对象的自有属性设置为不可配置(即将configurable设为false),一样不能解封。
咱们能够利用Object.isSealed()
来判断这个对象是否封闭,传入一个对象,返回布尔值。
Object.freeze()
能够将对象冰冻,效果和上面的Object.seal()
同样,增长的效果是将这个对象的自有属性设置为不可写(即将writable设为false),一样不能解冻。Object.isFrozen()
能够判断这个对象是否冰冻。
根据属性查询值的方式咱们固然是众所周知了,[]
和.
,固然他们也能够设置和修改可写性为true的自有属性值
var o = {} Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: true, configurable: true } } ) o.x // => 1 o['x'] = 5 o.x // => 5 o.y = 5 o.y // => 1
delete
能够用户删除对象属性,能删除的属性只是该对象的自有属性
且属性配置性为true
的属性
让人感到意外的是,delete
只是断开属性和宿主对象的联系,而不会去操做属性中的属性。
检测属性共有三种方式,in
操做符,hasOwnProperty
和propertyIsEnumerable
in
能够检测对象的自有属性
和继承属性
,不受属性特性的影响
var o = {x: 1} 'x' in o // true 'y' in o // false 'toString' in o // true
hasOwnProperty
只能检测对象的自有属性
,不能检测继承属性
,不受属性特性的影响
var o = {x: 1} o.hasOwnProperty('x') // true o.hasOwnProperty('y') // false o.hasOwnProperty('toString') // false
propertyIsEnumerable
只能检测自有属性
,且要求这个属性的可枚举性为true
首先第一个方法是for/in
,这个方法能够枚举出当前对象可枚举(属性枚举性为true)的自有属性和继承属性
var o = Object.create({z: 1}) Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) for (p in o) {console.log(p)} // => x, z
第二个方法是Object.keys()
,这个方法能够枚举出当前对象的可枚举(属性枚举性为true)的自有属性
,返回值是一个数组
var o = Object.create({z: 1}) Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) Object.keys(o) // => ['x']
第三个方法是Object.getOwnPropertyNames
,它能够枚举出当前对象全部的自有属性(不受枚举性影响)
Object.defineProperties( o, { x: { value: 1, writable: true, enumerable: true, configurable: true }, y: { value: 1, writable: false, enumerable: false, configurable: true } } ) Object.getOwnPropertyNames(o) // => ['x', 'y']
JSON.stringify()
和JSON.parse()