工厂模式
function cratedPerson(name) {
var o = new Objec();
o.name = name;
o.getName = function() {
console.log(this.name);
}
return o;
}
var person = cratedPerson('bajiu');
缺点:对象无法识别,因为所有的实例都指向一个原型
构造函数
function Person(name) {
this.name = name;
this.getName = function() {
console.log(this.name);
}
}
var person = new Person('bajiu');
优点:示例可以识别为一个特定的类型。
缺点:每次创建实例时,每个方法都会被创建一次。
构造函数模式优化
function Person(name) {
this.name = name;
this.getName = getName;
}
function getName() {
console.log(this.name);
}
var person = new Person('bajiu');
优点:解决了每个方法都要被重新创建的问题
缺点:如果多个方法,就会新增多个全局方法(非常怪异)
原型模式
function Person(name) {};
Person.prototype.name = 'bajiu';
Person.prototype.getName = function() {
console.log(this.name);
}
var person = new Person();
优点:方法不会重新创建。
缺点:
- 所有的属性和方法都是共享
- 不能初始化参数
原型模式优化1
function Person(name) {};
Person.prototype = {
name: 'baijiu',
sayName: function() {
console.log(this.name);
}
}
var person = new Person();
优点:封装性更高。
缺点:重写了原型,丢失constructor
属性
原型模式优化2
function Person(name) {};
Person.prototype = {
constructor: Person,
name: 'baijiu',
sayName: function() {
console.log(this.name);
}
}
var person = new Person();
优点:示例可以通过constructor
属性周到所属构造函数。
缺点:
- 所有的属性和方法都是共享
- 不能初始化参数
组合模式
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
console.log(this.name);
}
var person = new Person;
优点: 该共享的共享,该私有的私有,使用最广泛的方式
缺点:封装性不够好
动态原型模式
function Person(name) {
this.name = name;
if(typeof this.getName !== 'function') {
Person.prototype.getName = function() {
console.log(this.name);
}
}
}
var person = new Person();
注意:使用动态原型模式时,不能用对象字面量重写原型。
原因如下:
function Person(name) {
this.name = name;
if(typeof this.getName !== 'function') {
Person.prototype = {
constructor: Person
getName: function() {
console.log(this.name);
}
}
}
}
var person1 = new Person('bajiu');
var person2 = new Person('kiki');
person2.getName(); // kiki
person1.getName(); // 报错
原因和new的执行步骤有关:
- 首先创建一个对象
- 将对象的原型指向 Person.prototype
- 然后执行Person.apply(obj)
- 返回对象
寄生构造函数模式
寄生式继承的思路与(寄生)构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部一某种方式增强对象,对后再想真的是他做了所有工作一样返回对象。
function Person(name) {
var o = {};
o.name = name;
o.getName = function() {
console.log(this.name);
}
return o;
}
var person = new Person();
console.log(person instanceof Person); // false
console.log(person instanceof Object); // true
使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率,这点有构造函数模式类似。
寄生组合式继承
组合继承式JS最常用的继承模式;不过,它同样也存在不足。组合继承最大的问题就是无论什么情况下,都会调用两次父类的构造函数;一次实在创建子类原型的时候,另一次实在子类构造函数内部。寄生组合式继承就是为了降低调用父类构造函数的开销而出现的。
function extend(subClass, superClass) {
var prototype = Object.create(superClass.prototype);
prototype.consturctor = subClass;
subClass.prototype = prototype;
}
extend
的高效率体现在他没有调用superClass构造速度,因此避免了在subClass.prototype
上面创建不必要多余的属性。同时,原型链还能保持不变,因此还能正常使用instanceof
和isPrototypeOf()
方法。
稳妥构造函数模式
function person(name) {
var o = {};
o.name = name;
o.getName = function() {
console.log(name);
}
return o;
}
var person = new Person('bajiu');
person.getName(); // bajiu
person.name = 'kiki';
person.getName(); // bajiu
console.log(person.name); // kiki
所谓稳妥对象,指的是没有公共属性,而且其方法不引用this
对象。
与寄生构造函数模式有两点内不同:
- 新建的实例方法不引用this
- 不实用new操作符调用构造函数
稳妥对象最适合在一些安全环境中,稳妥构造函数模式也跟工厂模式一样,无法识别对象的所属的类型