繼承方式一:函數
function P1(){ this.name = "nn";
this.eat = function(){
console.log("I am eating!")
} } P1.prototype.say = function(){
console.log("say Hi!")
} function C1(){ this.type = "tt"; this.arr = [1,2,3];
P1.call(this) }
var c1 = new C1();
console.log(c1.name); // nn
console.log(c1.eat()); // I am eating!
console.log(c1.say()); //報錯 Uncaught TypeError: c1.say is not a function
因而可知,這種方式下能夠繼承父類自身的的屬性和方法,不能繼承原型鏈上的屬性和方法
繼承方式二:this
function P2(){ this.name = "nn"; this.arr = [1,2,3]; this.eat = function(){ console.log("I am eating!"); } } P2.prototype.say = function(){ console.log("say Hi!"); } function C2(){ this.type = "tt"; } C2.prototype = new P2(); var c2 = new C2();
var c21 = new C2();
console.log(c2.name) // nn
console.log(c2.eat()) // I am eating!
console.log(c2.say()); // say Hi!
c2.arr.push(4);
console.log(c2.arr) // [1,2,3,4]
console.log(c21.arr); // [1,2,3,4]
因而可知,C2經過protopype把P2做爲他的原型鏈,實現了繼承,繼承了P2的全部屬性和方法,可是有一個問題就是對於引用的數據類型,一旦其中一個實例對引用類型改變,全部的實例化對象的引用類型值也改變了,就像是例子中的arr
繼承方式三:spa
function P3(){ this.name = "nn"; this.arr = [1,2,3]; this.eat = function(){ console.log("I am eating!"); } } P3.prototype.say = function(){ console.log("say Hi!"); } function C3(){ this.type = "tt"; P3.call(this) } C3.prototype = new P3(); var c3 = new C3(); var c31 = new C3();
console.log(c3.name) // nn
console.log(c3.eat()) // I am eating!
console.log(c3.say()); // say Hi!
c3.arr.push(4);
console.log(c3.arr) // [1,2,3,4]
console.log(c31.arr); // [1,2,3]
爲了解決2中出現的問題,利用了 P3.call(this) 這個方法,使得在每一個實例自己都有父親的全部屬性和方法,而不是去取原型鏈上的引用類型
繼承方式四:prototype
function P4(){ this.name = "nn"; this.arr = [1,2,3]; this.eat = function(){ console.log("I am eating!"); } } P4.prototype.say = function(){ console.log("say Hi!"); } function C4(){ this.type = "tt"; P4.call(this) } C4.prototype = P4.prototype; var c4 = new C4(); var c41 = new C4();
這種方法看起來已經解決上面遇到的全部問題,
方式一的不能繼承父元素的原型鏈上的方法,
方式二的修改原型鏈上引用類型會修改該全部實例的問題,
方法三的重複的實例化構造函數的問題,
可是其實方式二,三,四都還有一個問題,就是他們沒法去判斷誰是子元素的直接父元素,
instanceof只能判斷構該構造函數的實例在這條原型鏈上,好比c4 instanceof P4 結果爲true,c4 instanceof Object的結果也爲 true
實際上 C4.prototype.constructor === P4 爲 true
爲了解決這個問題 能夠參考方式五
繼承方式五:code
function P5(){ this.name = "nn"; this.arr = [1,2,3]; this.eat = function(){ console.log("I am eating!"); } } P4.prototype.say = function(){ console.log("say Hi!"); } function C5(){ this.type = "tt"; P5.call(this) } C5.prototype = Object.create(P5.prototype); C5.prototype.constructor = C5
var c5 = new C5(); var c51 = new C5();
備註:使用Object.create()建立的js對象,沒有constructor
好了,這就是對原型鏈以及繼承的理解與實現,後續有新內容再繼續補充!對象