標籤:
1、原廠模式
function CreatePerson(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.showName = function(){ alert(this.name); } return o;}var person1 = CreatePerson(‘王五‘,‘25‘,‘Coder‘);
可以按照上述方式批量產生包含所有必要資訊的CreatePerson對象 並且可以反覆調用
缺點是 無法解決對象識別的問題
2、建構函式模式
// 建構函式模式function CreatePerson(name,age,job){ this.name = name; this.age = age; this.job = job; this.showName = function(){ alert(this.name); } }var person1 = new CreatePerson(‘王五‘,‘25‘,‘Coder‘);var person2 = new CreatePerson(‘王五‘,‘25‘,‘Coder‘);
此時 有如下幾個優點
- 沒有原廠模式下的顯式的建立對象
- 直接將屬性和方法賦給了this對象
- 並且沒有return語句等缺點
缺點:
- 必須用new操作符來建立一個新的執行個體
- 方法不公用
pesron1和pesron2是兩個不同的執行個體 指向不同地址 所以不相等
console.log( person1 == person2); //false
但是兩個對象都擁有constructor屬性 並且該屬性指向CreatePerson
1 console.log( person1.constructor == CreatePerson); //ture2 console.log( person1.constructor == person2.constructor); //true
本來constructor屬性是用來標識物件類型的,但是現在有更多的標識物件類型的方法 instanceof
1 console.log( person1 instanceof Object ); //true2 console.log( person1 instanceof CreatePerson ); //true
方法不公用
1 console.log( person1.showName == person2.showName); //false
3、原型模式
每一個函數都有prototype原型屬性 這個屬性是一個指標 指向一個對象 可以用這個原型來實現方法的公用
1 // 原型模式 2 function CreatePerson(name,age,job){ 3 this.name = name; 4 this.age = age; 5 this.job = job; 6 } 7 8 CreatePerson.prototype.showName = function(){ 9 alert(this.name);10 } 11 12 var person1 = new CreatePerson(‘王五‘,‘25‘,‘Coder‘);13 var person2 = new CreatePerson(‘王五‘,‘25‘,‘Coder‘);
此時的方法公用
1 console.log(person1.showName == person2.showName); //true
未完待續。。。。。。。。。。。。。。。
建立一個名為Person的建構函式
function Person(name,sex){ this.name = name; this.sex = sex; } Person.prototype.showName = function(){ console.log(this.name); } Person.prototype.showSex = function(){ console.log(this.sex); } // 建立一個Person建構函式的執行個體 var person1 = new Person(‘張三‘,‘男‘); person1.showName(); //張三 person1.showSex(); //男
再建立一個名為Worker的建構函式
通過call()或者apply()來實現繼承父級的屬性
常見的錯誤繼承方法
function Worker(name,sex,job){ //建構函式偽裝 將Worker建構函式中this傳到Person中 //繼承父級的屬性 call來改變範圍 也可以使用apply // //第一種call 必須要將第二個參數全部列舉出來 Person.call(this,name,sex); //第二種apply 參數為數組 // Person.apply(this,[name,sex]); this.job = job; } // 原型鏈 繼承父級的原型方法 // 第一種 淺複製 指向同一地址 對Worker的方法會影響到父級Person 不推薦使用 Worker.prototype = Person.prototype; Worker.prototype.showJob = function(){ console.log(this.job); } var worker1 = new Worker(‘李四‘,‘女‘,‘UI設計師‘); worker1.showName(); //李四 worker1.showSex(); //女 worker1.showJob(); //UI設計師
此時
// 問題出在父級也擁有子級的showJob方法 console.log(Person.prototype); //Object { //showJob: () //showName: () //showSex: () //__proto__: Object //}
這是由於前複製
Worker.prototype = Person.prototype;
父級和子級指向同一對象的地址 對子級的修改同樣會影響到父級 為了避免這樣的情況得new一個新對象來開闢新的地址來存放對象
// 第二種 寄生建構函式模式 Worker.prototype = new Person(); // 或者 通過迴圈的方式 for( var i in Person.prototype){ Worker.prototype[i] = Person.prototype[i]; }
此時
console.log(Person.prototype);
沒有showJob的方法
instanceof ...的執行個體
console.log(Person instanceof Object) //trueconsole.log(person1 instanceof Object) //trueconsole.log(person1 instanceof Person) //trueconsole.log(person1 instanceof Worker) //falseconsole.log(worker1 instanceof Person) //true
JS物件導向筆記