1、通过Object构造函数或者对象字面创建单个对象
这些方式有明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码,为了解决这个问题,出现了工厂模式。
2、工厂模式
考试在es中无法创建类(es6前),开发人员发明了一种函数,用函数来封装以特定接口创建对象的细节。(实现起来是在一个函数内创建好对象,然后把对象返回)
函数createPerson()能够根据接收的参数来构建一个包含所有必要信息的Person对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题,即怎么知道一个对象类型。随着js发展,又出现了一个模式。
3、构造函数模式
像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境,此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
与工厂模式相比,具有以下特点:
1、没有显式创建对象;
2、直接将属性和方法赋值了this对象;
3、没有return语句;
4、要创建新实例,必须使用NEW操作符;(否则属性和方法将会被添加到window对象)
5、可以使用instanceof操作符检测对象类型;
构造函数的问题;
构造函数内部的方法会被重新创建,不同实例内的函数是不相等。可以通过将方法移到构造函数外部解决一些问题,但是面临新的问题:封装性不好。
这些问题可以通过原型模式解决。
4、我们创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有势力共享的属性和方法。(prototype就是通过调用构造函数而创建的那个对象实例的原型对象)
使用原型对象的好处是可以让所有对象实例共享它所包含的属性和放大,换句话说,不必在构造函数中定义对象实例的信息,而是将这些信息直接添加到原型对象中。
更常见的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象,并重设constructor属性。
原型对象的问题:
1、他省略了为构造函数传递初始化参数这一环节,结果所有实例默认情况下都将取相同的属性值,虽然这会在一定程度带来一定不便,但不是最大问题,最大的问题是由其共享的本性所决定的,对于包含基本值的属性可以通过在实例上添加一个同名属性隐藏原型上的属性。然后,对于包含引用数据类型的值来说,会导致问题。
这些问题导致很少单独使用原型模式。
5、组合使用构造函数模式和原型模式
这是创建自定义类型的最常见的方式。
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。所以每个实例都会有自己的一份实例属性的副本,同时共享着对方法的引用,最大限度的节省了内存,同时支持向构造函数传递参数。
6、动态原型模式
这里只有sayName() 不存在的情况下,才会将他添加在原型中,这段代码只会在初次调用构造函数的时候才执行,这里对原型所做的修改,能够立刻在所有实例中得到反应。
7、Object.create()
es5定义了一个名为Object.create()的方法,它创建一个新对象,其中第一个参数是这个对象的原型,第二个参数对对象的属性进行进一步的描述。
8、另有寄生构造函数模式和稳妥构造函数模式