关于js继承的理解与实现

继承方式一:函数

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

好了,这就是对原型链以及继承的理解与实现,后续有新内容再继续补充!对象

相关文章
相关标签/搜索