1.字面量javascript
// 優勢:簡單方便 // 缺點:每建立一個對象都要從新寫,且建立多個比較佔內存 var obj1 = { name: 'liuhui1' }; var obj2 = new Object({ name: 'liuhui2' }); var obj3 = Object.create({ name: 'liuhui3' });
2.工廠模式html
// 優勢:改善了字面量方法建立多個類似對象的問題,不須要編寫重複的代碼 // 缺點:沒有解決對象是別的問題,不知道對象的類型是什麼 function person () { var obj = new Object(); obj.name = 'liuhui4'; obj.sayName = function () { console.log(this.name); }; return obj; } var obj4 = person(); console.log(obj4.sayName());
3.構造函數模式java
// 優勢:建立並定義了對象類型的屬性和方法,能夠標示爲特定的類型(自定義構造函數,原生:Object/Array) // 缺點:方法沒有被共享,每次實例一個對象都要重複綁定一個獨立的方法 function Person (name) { this.name = name; this.sayName = function () { console.log(this.name); }; this.newFun = newFun; } // 解決辦法:將方法寫在全局,可是就變成全局方法了跟封裝的觀念相違背了 // 新增代碼 function newFun () { console.log('new name: ' + this.name); } var obj5 = new Person('liuhui5'); console.log(obj5.sayName());
4.原型模式函數
// 優勢:將方法封裝到相應的原型對象上,私有並實例能夠共享這些屬性和方法 // 缺點:全部屬性和方法都共享了,改變實例的屬性和方法會影響原型對象上的屬性和方法 function Person1 () { } Person1.prototype = { constructor: Person1, name: 'liuhui6', sayName: function () { console.log(this.name); } }; var obj6 = new Person1(); console.log(obj6.sayName());
5.組合模式(構造函數+原型模式)尚未徹底理解優化
// 優勢:構造函數用於定義實例屬性和方法,原型模式用於共享定義的屬性和方法 function Person2 (name) { this.newName = function () { console.log(name); } } Person2.prototype = { constructor: Person2, name: 'liuhui7', sayName: function () { console.log(this.name); } }; var obj7 = new Person2(); var obj8 = new Person2('liuhui8');
1.藉助構造函數實現繼承ui
// 缺點:父級構造函數屬性和方法沒有被共享 function Parent1 () { this.name = 'parent1'; this.play = [1, 2, 3]; } function Child1 () { Parent1.call(this); // 關鍵:執行父級構造函數,深複製 this.type = 'child1'; } Parent1.prototype.say = function () { console.log('hello1'); }; console.log(new Child1()); var s1 = new Child1(); var s2 = new Child1(); s1.play.push(4); console.log(s1.play, s2.play, s1.hasOwnProperty('play'), 'test1');
2.藉助原型鏈實現繼承this
// 缺點:原型鏈上的屬性和方法是共享 function Parent2 () { this.name = 'parent2'; this.play = [1, 2, 3]; } function Child2 () { this.type = 'child'; } Parent2.prototype.say = function () { console.log('hello2'); }; Child2.prototype = new Parent2(); // 關鍵:將子級執行父級構造函數實現繼承,淺複製 console.log(new Child2(), new Child2().say()); var s3 = new Child2(); var s4 = new Child2(); s3.play.push(4); console.log(s3.play, s4.play, s3.hasOwnProperty('play'), 'test2');
3.組合方式prototype
// 缺點:父級構造函數執行了兩遍 function Parent3 () { this.name = 'parent3'; this.play = [1, 2, 3]; } function Child3 () { Parent3.call(this); // 關鍵1 this.type = 'child3'; } Parent3.prototype.say = function () { console.log('hello3'); }; Child3.prototype = new Parent3(); // 關鍵2 var s5 = new Child3(); var s6 = new Child3(); s5.play.push(4); console.log(s5, s6, s5.hasOwnProperty('play'), 'test');
4.組合方式優化1code
// 缺點:實例屬性constructor指向父級構造函數,使用instanceof不能正確判斷對象類型 function Parent4 () { this.name = 'parent4'; this.play = [1, 2, 3]; } function Child4 () { Parent4.call(this); this.type = 'child4'; } Parent4.prototype.say = function () { console.log('hello4'); }; Child4.prototype = Parent4.prototype; Child4.prototype.constructor = Child4; // 新增代碼,讓實例指向其真實的構造函數 var s7 = new Child4(); var s8 = new Child4(); s7.play.push(4); console.log(s7, s8); // 判斷是子原型Child4實例化仍是Parent4直接實例化的 console.log(s7 instanceof Child4, s8 instanceof Parent4); // 判斷不了 console.log(s7.constructor, s8.constructor, s7.hasOwnProperty('play'), 'test');
5.組合方式優化2htm
function Parent5 () { this.name = 'parent5'; this.play = [1, 2, 3]; } function Child5 () { Parent5.call(this); this.type = 'child5'; } Parent5.prototype.say = function () { console.log('hello5'); }; Child5.prototype = Object.create(Parent5.prototype); Child5.prototype.constructor = Child5; var s9 = new Child5(); var s10 = new Child5(); s9.play.push(4); console.log(s9 instanceof Child5, s9 instanceof Parent5); console.log(s9.constructor, s10.constructor, s9.hasOwnProperty('play'), 'test11');