最近再次拿起《Javascript高级程序设计(第三版)》,真的感觉经典的书何时读都会很有收获,相信好多人都推荐过这本书,这次也是给大家分享下其中创建对象这个主题,也是让自己更加深刻一下。
一、工厂模式
1 | 例:function createPerson(name,age,job) { |
二、构造函数模式
1 | 例:function Person(name,age,job) { |
特点:
①、没有显示地创建对象;
②、直接将属性和方法赋给了this对象;
③、没有return语句
创建Person的新实例,必须通过new操作符,以这种方式调用构造函数会经历以下四个步骤:
①、创建一个新对象;
②、将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
③、执行构造函数中的代码(初始化对象);
④、返回新对象
这样就能够通过instanceof检测实例了,对象也就具备了类型
三、原型模式
1 | function Person( ) { |
缺点:原型模式的最大问题是由其共享的本性所导致的,这种共享对于函数非常合适,对于那些包含基本值的属性倒也还说得过去,通过在实例中添加一个同名属性,可以隐藏原型中的属性,然后对于引用类型值的属性来说,问题就比较突出了,只要一个实例改变,则所有是例都会发生同样的改变,因为实例只是有一个指针指向这个共享的引用类型,所以在开发中经常采用下面的这种组合模式;
四、组合使用构造函数模式和原型模式
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时共享着对方法的引用,最大限度地节省了内存,另外,这种模式还支持向构造函数传参,可以说是集两种模式之长;
五、动态原型模式
它把所有的信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点,换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型;
例:
1 | function Person(name,age,job) { |
这里只会在sayName( )方法不存在的情况下,才会将它添加到原型中,其中,if语句检查的可以是初始化之后应该存在的任何属性和方法-不必用一大堆if语句检查每个属性和每个方法,只要检查其中一个即可,对于采用这种模式创建的对象,还可以使用instanceof操作符确定它的类型;
注意:使用这种动态原型模式时,不能使用对象字面量重写原型,如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系;
六、寄生构造函数模式
这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的象,从表面上看,这个函数很像典型的构造函数;
例:
1 | function Person(name,age,job) { |
在这个例子中,除了使用new操作符并把使用的包装函数叫做构造函数之外,这个模式跟工厂模式其实是一模一样的。构造函数在不返回值的情况下,默认会返回新对象实例,而通过在构造函数末尾添加一个return语句,可以重写调用构造函数时返回的值,如果是简单数据类型直接忽略,是引用类型的话是直接返回这个对象。
这个模式可以在特殊情况下用来为对象构造函数,注意一下接下来的说明:返回的对象和构造函数或与构造函数的原型属性之间没有关系,也可以说,构造函数返回的对象与构造函数外部创建的对象没有什么不同,也就不能一栏instanceof操作符来确定对象类型了。只是应用一些很少的特殊情况(可以起到保护内部数据的作用)
假设我们想创建一个具有额外方法的特殊数组,由于不能直接修改Array构造函数,因此可以使用这个模式。
1 | function SpecialArray( ) { |
七、稳妥构造函数模式
道格拉斯.克罗克福德发明了Javascript中的稳妥对象这个概念,指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(这些环境中会禁止this和new)或者防止被其他应用程序(如Mashup程序)改动时使用。稳妥构造函数与寄生构造函数模式类似,但有两点不同:一是新创建对象的实例方法不引用this;二是不使用new操作符调用构造函数;
例:
1 | function Person(name,age,job) { |
这样变量friend中保存的是一个稳妥对象,而除了调用sayName()方法以外,没有别的方式可以访问其数据成员,即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的方法访问传到构造函数中的原始数据。这种模式提供的这种安全性,使得它非常适合在某些安全执行环境提供的环境下使用,与寄生构造函数模式类似,使用稳妥构造函数创建的对象与构造函数之间也没有关系,因此instanceof操作符对这种对象也没有意义,其实我现在理解主要也是利用了闭包的思想,用函数包起来之后去保护一些私有变量;