Javascript中创建对象的几种类型总结

目录

 

1. Object构造函数或对象字面量

2. 工厂模式

3. 构造函数模式

4. 原型模式

5. 组合使用构造函数模式和原型模式

6. 动态原型模式

7,寄生构造函数模式

8. 稳妥构造函数模式


1. Object构造函数或对象字面量

Javascript中创建对象的几种类型总结

但这两种方式有个很明显的缺点:

创建很多对象时,会产生大量的重复代码

为解决这个问题,人们开始使用工厂模式的一种变体

2. 工厂模式

因为ECMAScript中无法创建类

所以开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节

Javascript中创建对象的几种类型总结

工厂模式缺点

工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)

就是说使用工厂模式创建的对象无法判断它属于哪个具体引用类型的对象

 

3. 构造函数模式

使用构造函数模式可以创建自定义引用类型

按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头

Javascript中创建对象的几种类型总结

通过自定义构造函数创建的对象都有一个constructor属性,该属性指向它所属的引用类型(这里就是Person)

 

Javascript中创建对象的几种类型总结

 

可以说,constructor属性就是用来标识对象类型的

也可以使用instanceof操作符来检测对象类型

Javascript中创建对象的几种类型总结

 

构造函数模式胜过工厂模式的地方在于:

创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型

 

构造函数模式的缺点:

以上面的Person构造函数为例,每创建一个Person引用类型的对象,就会同时创建一个sayName函数

但是所有的Person对象的sayName函数内容都是相同的,这就造成了资源的浪费

理想的解决方案是所有的Person对象只需要有一个共同的sayName函数

 

4. 原型模式

每个函数都有一个prototype(原型)属性,这个属性指向一个包含可以由特定类型的所有实例共享的属性和方法的对象

原型模式就是将对象实例的信息(属性和方法)直接添加到原型对象中,让所有实例共享这些信息

Javascript中创建对象的几种类型总结

 

①构造函数、原型对象和实例之间的关系

构造函数的prototype属性指向原型对象

原型对象会自动获得一个constructor属性,指向构造函数

实例内部包含一个指针叫[[Prototype]],指向原型对象。

Javascript中创建对象的几种类型总结

②确定实例与原型对象之间是否存在“连接”

虽然在所有的实例中都无法访问到[[Prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系

Javascript中创建对象的几种类型总结

另外,ECMAScript5增加了一个新方法,叫Object.getPrototypeOf()

这个方法返回[[Prototype]]的值

原型模式中的属性屏蔽机制

当为对象添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性

换句话说,添加这个属性只会阻止我们访问原型中的那个属性,但不会修改那个属性

Javascript中创建对象的几种类型总结

使用delete操作符可以完全删除实例属性,从而让我们能够重新访问原型中的属性

Javascript中创建对象的几种类型总结

原理图:

Javascript中创建对象的几种类型总结

 

使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中

Javascript中创建对象的几种类型总结

in操作符会在通过对象能够访问给定属性时访问true,无论该属性存在于实例中还是原型中

Javascript中创建对象的几种类型总结

③遍历对象中的属性

有三种方法可以遍历对象中的属性:

第一种:使用for-in语法

遍历实例与原型中可枚举的属性(即将[[Enumerable]]标记为true的属性)

第二种:使用Object.keys()方法

得到实例中可枚举属性的数组

第三种:使用Object.getOwnPropertyNames()方法

得到实例中可枚举或不可枚举属性的数组

Javascript中创建对象的几种类型总结

④更简单的原型语法

Javascript中创建对象的几种类型总结

这里重写了constructor属性,会导致它的[[Enumerable]]特性被设置为true

为了使constructor属性变回不可枚举,可以使用ECMAScript5的Object.defineProperty()方法

Javascript中创建对象的几种类型总结

⑤原型模式的缺点

用原型模式创建的所有实例在默认情况下都将取得相同的属性值

所以,如果一个实例修改属性值可能造成另一个调用此属性的实例的错误

 

5. 组合使用构造函数模式和原型模式

构造函数模式用于定义各个实例独有的实例属性,使得各个实例有各自的属性

原型模式用于定义各个实例共享的方法和属性

Javascript中创建对象的几种类型总结

6. 动态原型模式

通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型

Javascript中创建对象的几种类型总结

动态原型模式的一个优点是不存在重写原型对象

 

7,寄生构造函数模式

这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象

Javascript中创建对象的几种类型总结

构造函数在不返回值的情况下,默认会返回新对象实例

而通过在构造函数的末尾添加一个return语句,可以重写调用构造函数时返回的值

所以,构造函数返回的对象与构造函数或者与构造函数的原型属性之间没有关系

构造函数可以用来扩展某些引用类型的功能,以获得一个扩展功能的引用类型,比如上面的SpecialArray

 

8. 稳妥构造函数模式

稳妥对象,指的是没有公共属性

稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:

一是新创建对象的实例方法不引用this

二是不使用new操作符调用构造函数

Javascript中创建对象的几种类型总结

稳妥构造函数的优点:

只有通过特定的方法才能访问到构造函数中的原始数据

稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环境下使用