繼承 所謂繼承就是子類繼承父類的特征與行為,使得子類對象具與父類相同的行為。但是javascript 是沒有class、抽象類、介面等抽象概念,javascript 只有對象,那麼js中是如何讓對象與對象之間產生繼承關係呢? 基於對象的繼承 在原型鏈中說過,如果在對象上沒有找到需要的屬性或者方法引用 ...
繼承
所謂繼承就是子類繼承父類的特征與行為,使得子類對象具與父類相同的行為。但是javascript 是沒有class、抽象類、介面等抽象概念,javascript 只有對象,那麼js中是如何讓對象與對象之間產生繼承關係呢?
基於對象的繼承
在原型鏈中說過,如果在對象上沒有找到需要的屬性或者方法引用,js引擎就會繼續在內部屬性[[prototype]] 指向的對象上進行查找。同理如果還是沒有找到需要的引用,就會繼續查找它的內部屬性[[prototype]]指向的對象,以此類推,層層向上直到找到對象的原型為null為止,這一系列的鏈接稱為原型鏈。所以在原型鏈中我才會js中的繼承是基於原型實現;
_proto_ 設計機制
任何對象都有一個特殊的內部屬性[[prototype]],[[prototype]]機制就是建立起對象之間的內部鏈接。如果有過後臺開發經驗的肯定會納悶,為什麼js要這樣設計?引入原型對象的意義又是什麼?為什麼不跟java、.net 一樣設計calss等等凝惑, 這裡推薦 阮一峰的《Javascript繼承機制的設計思想》;
組合繼承
組合繼承是比較常用的一種繼承方法,思路是使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。這樣,既通過在原型上定義方法實現了函數復用,又保證每個實例都有它自己的屬性。
1 //人 2 function Person(name, age) { 3 this.name = name; 4 this.age = age; 5 } 6 Person.prototype.SayName = function () { 7 return this.name; 8 }; 9 //父親 10 function Parent(work, country, name, age) { 11 this.work = work; 12 this.country = country; 13 this.parentInfo = function () { 14 return 'hello 大家好,我叫:' + this.name +' 我是一名:' + this.work + ',我來自:' + this.country; 15 } 16 Person.call(this, name, age);//父類型傳參 17 } 18 Parent.prototype = new Person();//重寫Parent的原型對象,讓parent的prototype 指向 Person 的實例 19 var myParent = new Parent('manager', 'China', 'Joel', 22); 20 console.log(myParent.SayName());//Joel 21 console.log(myParent.parentInfo());//hello 大家好,我叫:Joel 我是一名:manager,我來自:China 22 23 //兒子 24 function Child(work, country, name, age, sex) { 25 this.sex = sex; 26 this.childInfo = function () { 27 return 'hello 大家好,我叫:' + this.name + ' 我是一名:' + this.work + ',我來自美麗的:' + this.country
+ ',我是一個活潑可愛的 ' + this.sex; 28 } 29 Parent.call(this, work, country, name, age);//父類型傳參 30 } 31 32 Child.prototype = new Parent();//重寫Child的原型對象,讓Child的prototype 指向 Parent 的實例 33 var myBaby = new Child('child', '廣州', '超級飛俠-多多', 3, 'girl'); 34 console.log(myBaby.parentInfo());//hello 我是一名:child,我來自:廣州 35 console.log(myBaby.childInfo());//hello 大家好,我叫:超級飛俠-多多 我是一名:child,我來自美麗的:廣州,我是一個活潑可愛的 girl
這裡基類是人,子類是父親、兒子,這裡通過重寫原型對象以及在構造函數中調用父類的構造函數,並且用call改變了this 指針,從而達到兒子繼承了父親,父親繼承了人;
new 操作符
重要的事情在這裡說一次,之前在原型鏈中已經提過一次;
MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new 的解釋
當使用new去調用構造函數時,相當於執行了
1 var o = {}; 2 o.__proto__ = F.prototype;//實例跟原型對象之間建立了鏈接,實例跟構造函數之間沒有關係; 3 F.call(o);
總結
- 對象之間的鏈接通過[[prototype]]進行關聯
- new 操作符關鍵點
- prototype 是函數對象的屬性,_proto_ 是實例的內部屬性[[prototype]]
- 原型鏈是沿著_proto_鏈接進行查找