工厂模式 解决:对象字面量大量重复代码的问题(创建多个相似变量时) 问题:存在对象识别问题 function ceateObj(name,age){ var obj=new Object(); obj.name=name; obj.age-age; obj.showAge=function(){ alert(this.name) }
return obj; }
var person=createObj('aaa','22');
构造函数模式 解决了工厂模式无法解决对象识别问题
问题:每个方法都要在实例上重新创建一次,即两个实例访问的方法不一样 function Person(name,age){ this.name=name; this.age=age; this.showAge=function(){ alert(this.name) } } var person=new Person('aaa','11');
person instanceof Person;//true
person instanceof Object;//true
与工厂模式的区别:没有显式创建对象;直接将属性和方法赋给了对象;没有return语句;创建实例要用new 语句
原型模式: 解决实例共享属性和方法问题
问题:所有实例属性都相同,引用相同 function Person(){ } Person.prototype.name='aaa'; Person.prototype.age='11' Person.prototype.showAge=function(){ alert(this.name) } var person1=new Person(); var person2=new Person(); person1.showAge();//11 person2.showAge();//11
组合使用构造函数和原型模式 构造函数用于定义实例 原型模式用于定义方法和共享属性 function Person(name,age){ this.name=name; this.age=age; } Person.prototype.showAge=function(){ alert(this.age) }
动态原型模式 优点:仅在需要的情况下定义原型方法 function Person(name,age){ this.name=name; this.age=age; if(typeof this.showAge!='function'){//只有初次调用构造函数时执行,不需要每个属性判断,只判断一个即可 Person.prototype.showAge=function(){ alert(this.age) } } }
寄生构造函数,本质和工厂方法一样,只是寄生方法重写return值覆盖了new构造函数的return this function Person(name,age){ var obj=new Object(); obj.name=name; obj.age=age; obj.showAge=function(){ console.log(this.age); } return obj; } var per=new Person('aa',11); per.showAge()
注意:返回的对象与构造函数或者与构造函数的原型属性之间没有关系,per instanceof Person为false
稳妥构造函数模式 稳妥对象就是没有公共属性,而且其方法也不引用this对象,不使用new操作符调用构造函数 function Person(name,age){ var obj=new Object(); obj.sayAge=function(){ console.log(age);//这种模式创建的方法除了调用sayage以外没有其他方法可以访问age属性 } }
继承
原型链继承 function Super(){ this.color=['red','yellow']; this.test='false'; } Super.prototype.getColor=function(){ return this.color; } function sub(){ this.color=['fff']; } Sub.prototype=new Super(); //问题:通过这方式创建的属性如果子类中没有相同名称的属性如color,则会想原型属性一样共享如test //问题二:在创建子类型的实例时,不能向超类的构造函数中传递参数,没有办法在不影响所有实例的情况下给超类的构造函数传递参数
借用构造函数继承 function Super(){ this.color=['red','yellow']; } function sub(){ Super.call(this); } //方法都只能在构造函数中定义,不能复用
组合继承 function Super(name,age){ this.name=name; this.age=age; } Suoer.prototype.showAge=function(){ console.log(this.name); } function Sub(name,age){ Super.call(this,name,age); } Sub.prototype=new Super(); Sub.prototype.constructor=Sub;//修改指向
原型式继承 function Create(o){ function F(){} F.prototype=o; return new F(); } var data={ name:'aa', age:11, color:['red'] } var c1=Create(data); var c2=Create(data); c1.name='cc'; c1.color.push('yellow') console.log(c2.name)//aa console.log(c1.name)//cc console.log(c2.color)//[red,yellow]浅复制
寄生式继承 function anotherCreate(o){ var clone=Create(o); clone.say=function(){ console.log(this.name) } return clone; } var clone=anotherCreate(data); clone.say()
//类似于工厂模式
寄生组合式继承 组合式继承最大的问题是无论什么情况下都会调用两次超类,一次是创建子类原型时,一次是在子类的构造函数内部 function inherite(super,sub){ var prototype=Create(super.prototype); prototype.constructor=sub; sub.prototype.prototype; } function Super(name){ this.name=name; } Super.prototype.say=function(){ console.log(this.name); } function Sub(naem){ Super.call(this,name); } inherite(Super,Sub)