简介

除了字符串、数字、true、false、null、undefined之外,JavaScript中的值都是对象。

对象是JavaScript的基本数据结构(JavaScript权威指南上说对象是JavaScript的基本数据类型不太准确,应该是基本数据结构)。对象是一种复合值:它将原始值或者其他对象聚合在一起,可以通过名字访问这些值。对象也可以看做是属性的无序集合。每个属性都是一个key-value对。JS对象的属性名是字符串,因此我们也可以把对象看成是从字符串到值的映射。

这种基本数据结构还有很多叫法,比如散列(hash)、散列表(hashable)、字典(dictionary)、关联数组(associative array)。

然而对象不仅仅是key-value的映射,JavaScript对象还可以从一个称为原型的对象继承属性。对象的方法通常是继承的属性。这种“原型式继承”(prototypal inheritance)是JavaScript的核心特征。

JavaScript对象是动态的,可以新增属性也可以删除属性。这一点非常重要。

对象的常见用法

对象的常见用法包括创建、设置、查找、删除、检测和枚举属性。

对象特性

除了包含属性外,每个对象还拥有三个相关的对象特性(object attribute)。分别是对象的原型、对象的类、对象的扩展标记特性。

  • 对象的原型(prototype):对象的原型也是一个对象(object)。对象的原型指向这个对象。本对象的属性继承自它的原型对象。笔者认为,这个原型对象就是本对象所属的类。类似于Objective-C语言中的类对象和元类对象。
  • 对象的类(class):对象的类是一个字符串(string),表明这个对象属于哪个类。
  • 对象的扩展标记(extensiable flag):是一个boolean值。表明是否可以向该对象添加新属性。

属性特性

对象的属性除了包含key-value对,每个对象属性还拥有三个相关值,这三个值称为“属性特性”。分别是可写、可枚举、可配置特性。

  • 可写:表明是否可以设置该属性的值,相对于不可写,即只读。
  • 可枚举:表明是否可以通过for/in循环返回该属性。
  • 可配置:表明是否可以删除或修改该属性。

注意:在ES5之前,通过代码给对象创建的所有属性都是可写、可枚举、可配置的。在ES5及其之后,我们可以对这些属性加以配置。

对象分类

  • 内置对象(native object):内置对象很容易理解,是由ES规范定义的类和对象。例如:数组、函数、日期、正则表达式。
  • 自定义对象(user-defined object):是由运行中的JavaScript代码创建的对象,通常是开发者在代码中自定义的对象。
  • 宿主对象(host object):是由JavaScript解释器锁嵌入的宿主环境(比如Web浏览器)所定义的。

属性分类

  • 继承属性(inherited property):是在对象所属的原型对象中定义的属性,该属性是继承而来的。
  • 自有属性(own property):相对于继承属性,是直接在对象中定义的属性。

创建对象

JavaScript中有3中创建对象的方式。分别是通过对象直接量、关键字new、Object.create()函数创建对象。

  • 对象直接量创建

    使用对象直接量创建对象是最简单的方式。对象直接量就是一个对象,就像我们可以用一对方括号初始化一个数组一样,我们也可以使用一个对象直接量初始化一个对象。对象直接量是由若干个key-value对组成的映射表,key-value对之间用逗号分隔,外层用花括号括起来。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var empty = {}
    var point = {x: 0, y: 0}
    var book = {
    name: "《JavaScript》",
    "for": "JavaScript Developer",

    "author": {
    firstName: "xxx",
    lastName: "xxx"
    }
    }

注意:在ES3中,保留字作为属性名必须使用引号(比如上米昂book对象中的for属性),而在ES5中则没有这个要求。

  • 通过new关键字创建对象

    1
    2
    3
    var a = new Array()
    var d = new Date()
    var r = new RegExp("js")
  • Object.create()函数创建对象

    1.ES5中定义了一个名为Object.create()的方法。这个方法接收两个参数,第一个参数是对象的原型。第二个参数是可选参数,这个可选参数用以对对象的属性进行进一步描述。

2.Object.create()是一个静态函数,在其他语言中可叫做类方法、静态方法。这是由Object类直接调用的方法,而不是由某个对象调用。
3.通过Object.create()方法,可以通过任意原型创建新对象。也就是可以使任意对象可被继承。

使用Object.create()创建对象,只需要传入他的原型即可。如下:

1
var point = Object.create({x:1, y:2}) // point对象继承了x、y属性。

可以通过传入null来创建一个没有原型的对象,这个对象不会继承任何东西,甚至不会继承toString()方法。也就是说,这个对象将不能使用”+”运算符如下:

1
var obj = Object.create(null) // obj 没有原型

如果想创建空对象(比如通过对象直接量{}创建的对象或通过new Object()创建的对象),需要传入Object.prototype。如下:

1
var empty = Object.create(Object.prototype) // 等同于 var empty = {} 或 var empty = new Object()

原型(prototype)

上面我们说过,对象不仅仅是key-value的映射,JavaScript对象还可以从一个称为原型的对象继承属性。对象的方法通常是继承的属性。这种“原型式继承”(prototypal inheritance)是JavaScript的核心特征。在JavaScript中,绝大多数对象都具有原型,原型也是对象。对象有自己的属性,也可以从原型中继承属性。

1.所有通过对象直接量创建的对象都具有同一个原型对象(即通过对象直接量创建的对象继承的属性是一样的),他们的原型都是Object.prototype。
2.通过关键字new和构造函数创建的对象的原型就是构造函数的prototype属性的值。Array的构造函数就是Array,那么new Array()创建的对象的原型就是Array.prototype。Date的改造函数就是Date,那么new Date()创建的对象的原型就是Date.prototype。
所以,通过对象直接量{}、new Object()创建的对象都继承自Object.prototype。
综上:对象的原型都可以通过对象类型.prototype获取。

上面说JavaScript中,绝大多数对象都具有原型。所以也存在没有原型的对象,但为数不多,Object.prototype就是其中之一。Object.prototype不继承任何属性,他的的属性都是自有属性。
构造函数就是对象的类型。Date型对象的构造函数就是Date,Array型对象的构造函数就是Array,所有的内置构造函数以及大部分的自定义构造函数的原型都继承自Object.prototype。例如:
Array的原型是Array.prototype,Array.prototype的原型是Object.prototype.

敬请期待~