1,工廠模式javascript
//工廠模式 function createObiect(name,age){ var obj=new Object(); //建立對象 obj.name=name; //添加屬性 obj.age=age; obj.run=function(){ //添加對象方法 return this.name+this.age+'運行中....' }; return obj; //返回對象引用 } var box1=createObject('Lee',100); var box2=createObject('jact',200); alert(box1.run()); alert(box2.run()); //問題識別不出來,搞不清誰究竟是誰的對象
2, 構造函數模式java
fucntion Box(name,age){ this.name=name; this.age=age; this.run=function(){ return this.name+this.age+'運行中'; } } var box1=new Box('lee',100); var box2=new Box('jack',200); box1 instanceof Object //
使用構造函數和工廠模式的方法他們不一樣之處以下:函數
《1,構造函數方法沒有顯示的建立對象(New Object())this
《2,直接將屬性和方法賦值給this對象prototype
《3,構造函數沒有return 對象,是後臺自動返回的指針
3,構造函數和普通函數的區別code
構造函數調用必須使用new ,建立構造函數名首字母大寫對象
4,對象冒充調用繼承
fucntion Box(name,age){ this.name=name; this.age=age; this.run=function(){ return this.name+this.age+'運行中'; } } var o=new Object(); Box.call(o,'lee',100); //對象冒充,把Box的功能都拿給了o對象 alert(o.run())
//對象冒充 function Person(name,age){ this.name = name; this.age = age; this.show = function(){ console.log(this.name+", "+this.age); } } function Student(name,age){ this.student = Person; //將Person類的構造函數賦值給this.student this.student(name,age); //js中其實是經過對象冒充來實現繼承的 delete this.student; //移除對Person的引用 } var s = new Student("小明",17); s.show(); var p = new Person("小花",18); p.show(); // 小明, 17 // 小花, 18
5,構造函數裏的方法究竟是基本類型仍是引用類型ip
fucntion Box(name,age){ this.name=name; this.age=age; this.run=function(){ //return this.name+this.age+'運行中'; this.run=run; } } //註明全局name變量會存在問題,換個名字就能夠,最好不要全局函數會 function run(){ //把構造函數內部的方法經過全局來實現引用地址一致 return this.name+this.age+'運行中'; } var box1=new Box('lee',100); //實例化後地址爲1 var box2=new Box('lee',100); //實例化後地址爲2 //alert(box1.name==box2.name); //true //alert(box1.age==box2.age); //true //alert(box1.run()==box2.run()); //true 構造函數體內的方法的值是至關的 alert(box1.run==box2.run); //false 由於他們比較的是引用地址
6,原型的缺點都是共享的,有些部分不但願共享
//原型的缺點 //共享是優勢也是缺點,若是box1和box2初始值不想同樣的,因此這裏是實現不了,都是共享的 function Box(){} Box.prototype={ constructor:Box, name:'lee', age:100, family:['哥哥','姐姐','妹妹'], run:function(){ return this.name+this.age+'運行中。。。' } } var box1=new Box(); alert(box1.family); //哥哥,姐姐,妹妹 box1.family.push('弟弟'); alert(box1.family); //哥哥,姐姐,妹妹,弟弟 var box2=new Box(); alert(box2.family); //哥哥,姐姐,妹妹,弟弟 //共享了box1添加後的引用的原型
7,組合構造函數+原型模式
//組合構造函數+原型模式 function Box(name,age){ //須要獨立的用構造函數 this.name=name; this.age=age; this.family:['哥哥','姐姐','妹妹']; } Box.prototype={ //保持共享的用原型 constructor:Box, run:function(){ return this.name+this.age+'運行中。。。' } } var box1=new Box('lee',100); alert(box1.family); //哥哥,姐姐,妹妹 box.family.push('弟弟'); alert(box1.family); //哥哥,姐姐,妹妹,弟弟 var box2=new Box('jack',200); alert(box2.family) //哥哥,姐姐,妹妹
8,動態原型模式
//動態原型模式 //能夠將原型封裝到構造函數裏 function Box(name,age){ this.name=name; this.age=age; this.family=['可可','姐姐','妹妹']; //這裏的運行次數是幾回呢? alert('原型初始化開始'); Box.prototype.run=function(){ return this.name+this.age+'運行中。。。' } alert('原型初始化結束'); } //原型的初始化,只要第一次初始化,就能夠了,不必每次構造函數實例化的時候都初始化 var box1=new Box('lee',100); alert(box1.run()); var box2=new Box('jack',200); alert(box2.run());
如下解決初始化屢次的狀況
function Box(name,age){ this.name=name; this.age=age; this.family=['可可','姐姐','妹妹']; if(typeof this.run !='function'){ //加上一個判斷就能夠解決屢次的初始化問題 Box.prototype.run=function(){ return this.name+this.age+'運行中。。。' } } } var box1=new Box('lee',100); alert(box1.run()); var box2=new Box('jack',200); alert(box2.run());
9,寄生構造函數=工廠模式+構造函數
//寄生構造函數=工廠模式+構造函數 function Box(name,age){ var obj=new Object(); obj.name=name; obj.run=function(){ return this.name+this.age+'運行中。。。' }; return obj; } var box1=new Box('Lee',100); alert(box1.run()); var box2=new Box('jack',200); alert(box2.run());
級寄生組合繼承
//臨時中轉函數 function obj(o){ function F(){}; F.prototype=o; return new F(); } //寄生函數 function create(box,desk){ var f=obj(box.prototype); f.constructor=desk; //調整指針 desk.prototype=f; } function Box(name,age){ this.name=name; this.age=age; } Box.prototype.run=function(){ return this.name+this.age+'運行中。。。' } function Desk(name,age){ Box.call(this,name,age) } //經過寄生組合繼承來實現繼承 create(Box,Desk); //這句話用來替代Desk.prototype=new Box();