Javascript继承机制

在JS中实现继承,大概有两种思路:

  • 一种是使用构造函数;

  • 另一种就是原型链继承。

但两者各有利弊,构造函数继承会造成资源的浪费,方法和数据难以复用;
原型链继承当有包含引用类型值的原型时,则容易造成数据上的混乱。
通过构造函数实现继承,这种继承方式有个最大的缺点,便是无法实现数据和方法的共享。

如下:

function Stark(name){
 2  this.name = name;
 3  this.words = 'Winter is coming. ';
 4 }
 5 var Dell= new Stark('Dell');
 6 var Lee = new Stark('Lee ');
 7 Stark.words = 'Summer is coming.'
 8 
 9 console.log(Dell.words); //Winter is coming.
10 console.log(Lee .words); //Winter is coming.`

Stack的words属性改变了,而继承的words属性却没变

于是为构造函数设置一个prototype属性:原型(prototype)

prototype属性包含一个对象,所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。

function Stark(name){
 2  this.name = name;
 3 }
 4 Stark.prototype.words = 'Winter is coming.';
 5 
 6 var Dell= new Stark('Dell');
 7 var Lee = new Stark('Lee ');
 8 
 9 console.log(Dell.words); //Winter is coming.
10 console.log(Lee .words); //Winter is coming.
11 
12 Stark.prototype.words = 'Summer is coming.';
13 console.log(Dell.words); //Summer is coming.
14 console.log(Lee .words); //Summer is coming.

子类有时候希望拥有自己的构造函数,则需要应用原型链

function Stark (){
 2   this.words = 'Winter is coming.';  
 3 }
 4 function Dell(){
 5   this.pet = 'Summer';  
 6 }
 7 function Lee (){
 8   this.favor = 'winter';
 9 }
10 Dell.prototype = new Stark();
11 Lee .prototype = new Dell();
12 
13 lee = new Lee ();
14 
15 console.log(lee .favor);  //winter
16 console.log(lee .pet);  //Summer
17 console.log(lee .words);  //Winter is coming.

这就是原型链继承。

让lee 的原型对象等于Dell的实例,而Dell的实例中包含一个指向Dell原型对象的内部指针;而Dell的原型对象又等于Stark的实例,Stark的实例中包含一个指向Stark原型对象的内部指针。这种关系可以层层递进,形成一条实例与原型的链条,这就是原型链。

但是当原型内包含引用类型值时,子类实例对属性做出修改后,其他子类也受到影响。

解决方法就是

在实现继承的时候,所有实例对象需要共享的属性和方法,可以放在prototype对象里面;那些不需要共享的属性和方法,就放在构造函数里面

猜你喜欢

转载自blog.csdn.net/weixin_43043994/article/details/82021656