前提知識
Javascript:必須知道的Javascript知識點之“原型鏈”
Javascript:必須知道的Javascript知識點之“this指針”
幾個內置核心方法學習
代碼示例
1 var Base = function (name) { 2 this.name = name; 3 }; 4 5 var base = new Base(); 6 7 console.log((base instanceof Object));//true 8 console.log((base instanceof Base));//true 9 console.log(Base.prototype.isPrototypeOf(base));//true 10 console.log(Object.prototype.isPrototypeOf(base));//true 11 console.log(base.hasOwnProperty("name"));//true 12 console.log(base.hasOwnProperty("toString"));//false 13 console.log(("name" in base));//true 14 console.log(("toString" in base));//true
圖形示意
instanceof
obj instanceof T,判斷obj.__proto__指向的原型鏈是否包含T.prototype。
isPrototypeOf
objLeft.isPrototypeOf(objRight),判斷objLeft是否包含在objRight.__proto__指向的原型鏈中。
hasOwnProperty
obj.hasOwnProperty(propertyName),判斷obj(不包括原型鏈)是否包含屬性“propertyName”。
in
propertyName in obj,判斷屬性“propertyName”是否包含在對象obj及其原型鏈中。
單繼承實現
在javascript中實現單繼承的思路是:讓ChildType.prototype.__proto__指向ParentType.prototype。
代碼示例
1 Function.prototype.extend = function (baseType) { 2 var tempType = function () { }; 3 tempType.prototype = baseType.prototype; 4 5 this.prototype = new tempType(); 6 this.prototype.constructor = this; 7 this.super = function () { 8 return baseType.prototype; 9 }; 10 }; 11 12 var Base = function (name) { 13 this.name = name; 14 }; 15 16 var Animal = function () { 17 Animal.super().constructor.apply(this, arguments); 18 }; 19 Animal.extend(Base); 20 21 var Dog = function () { 22 Dog.super().constructor.apply(this, arguments); 23 }; 24 Dog.extend(Animal); 25 26 var dog = new Dog('笨狗'); 27 console.log(dog.name);//笨狗 28 console.log(dog instanceof Base);//true 29 console.log(dog instanceof Animal);//true 30 console.log(dog instanceof Dog);//true
圖形示意
常見問題
問題:為什么要引入“tempType”,而不是直接“this.prototype = new baseType()”?
答案:“new baseType()”會導致構造方法被調用兩次。
問題:為什么不直接“this.prototype = baseType.prototype”?
答案:這樣的話,父子類型就會同時指向一個prototype,不符合繼承的語義。
摻入實現
參考文章:設計原則:請重新審視“多重繼承”,找機會擁抱一下“摻入(Mixin)”。
在javascript中實現摻入的思路是:拷貝MixinType.prototye包含的所有屬性到TargetType.prototype中。
代碼示例
1 Function.prototype.extend = function (baseType) { 2 var tempType = function () { }; 3 tempType.prototype = baseType.prototype; 4 5 this.prototype = new tempType(); 6 this.prototype.constructor = this; 7 this.super = function () { 8 return baseType.prototype; 9 }; 10 }; 11 12 var Base = function (name) { 13 this.name = name; 14 }; 15 16 var Animal = function () { 17 Animal.super().constructor.apply(this, arguments); 18 }; 19 Animal.extend(Base); 20 21 var Dog = function () { 22 Dog.super().constructor.apply(this, arguments); 23 }; 24 Dog.extend(Animal); 25 26 var dog = new Dog('笨狗'); 27 console.log(dog.name);//笨狗 28 console.log(dog instanceof Base);//true 29 console.log(dog instanceof Animal);//true 30 console.log(dog instanceof Dog);//true 31 32 Function.prototype.mixin = function (name, mixinType) { 33 this.mixins = {}; 34 this.mixins[name] = mixinType; 35 36 for (var property in mixinType.prototype) { 37 if (property in this.prototype) { 38 continue; 39 } 40 41 this.prototype[property] = mixinType.prototype[property]; 42 } 43 }; 44 45 var Pet = function () { 46 }; 47 Pet.prototype.aoao = function () { 48 console.log(this.name + ',嗷嗷!'); 49 }; 50 51 Dog.mixin('pet', Pet); 52 dog.aoao(); 53 console.log(dog instanceof Pet);//false
圖片示意
常見問題
問題:這種摻入實現是不是太簡單了?
答案:確實,但是能滿足80%的需求,摻入的主要目的就是代碼復用。
備注
由於“原型鏈”的限制,Javascript實現不了真正意義的“多重繼承”。