此次我们好好聊一聊对象这个东西,本次说的不是
array
,也不是
function
,而是
object
基本观点
对象是一种特别的数据类型,这类数据类型另有其他的许多叫法,比方“散列”,“散列表”,“字典”,“关联数组”。
对象依据建立者的角度,能够分为三类:内置对象
:是由javascript言语自身自定义的对象,大多数是一些预定好的组织函数类,比方Array
,Date
,Function
宿主对象
:是指javascript诠释器所嵌入的宿主环境定义的对象,比方HTMLElement就是宿主对象。自定义对象
:是指由开发者在代码中所建立的对象。
我们晓得对象的表达体式格局是:‘属性’:’值’
属性依据泉源差别,能够分为两类:自有属性
:是指直接在对象中定义的属性。继续属性
:是指在对象原型链中的属性。
与此同时,对象的属性还具有一些特征:可写
:代表是不是能够设置该对象所对应的该属性的值。可罗列
:代表是不是能够经由过程api罗列出该属性。可设置
:代表是不是能够删除或修正该属性。
记着上述观点,有助于我们举行下一步的明白。
建立对象
建立对象有三种体式格局:
第一种:对象直接量
var o = {}
var obj = {
a: 1,
'b': 2,
'min title': 3
}
第二种:经由过程new建立对象
var o = new Object()
第三种:Object.create()
该要领支撑传入两个参数,第一个参数是对象的原型(就是所建立出的对象的_proto_
的指向),第二个参数是对属性进一步的形貌(该参数可选,参数内容会在背面详解)
以下三种体式格局是等价的:
检测对象原型的要领除了instanceof
以外,另有一个isPrototypeOf()
,我们来看一下运用:
对象的getter和setter
我们起首再明白一个观点:
我们罕见的{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
关于属性的修正是有划定规矩和请求的,以下:
- 假如对象是不可扩大的,则能够编辑已有的自有属性,但不能给它增添新属性。
- 假如属性是不可设置的,则不能修正它的可设置性和可罗列性。
- 假如存取器属性是不可设置的,则不能修正其getter和setter要领,也不能将它转换为数据属性。
- 假如数据属性是不可设置的,则不能将它转换为存取器属性。
- 假如数据属性是不可设置的,则不能将它的可写性从false修正为true,但能够从true修正为false。
- 假如数据属性是不可设置且不可写的,则不能修正它的值。但是可设置但不可写属性的值是能够修正的(实际上是先将它标记为可写的,然后修正它的值,末了转换为不可写的)。
在这里,我们再看一下上面的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()