js 原型链与继承

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js 原型链与继承相关的知识,希望对你有一定的参考价值。

var A = function(){ this.name="xiaoming"; }
A.prototype.age=9;
var a = new A();
console.log(a.age); //9
技术分享图片
图中长方形代表实例对象a,圆形代表原型,三角形代表构造函数。由图可知:
a.__proto__ === A.prototype; //true
A.prototype.constructor===A; //true
A.prototype.__proto__===Object.prototype; //true
Object.prototype.__proto__===null; //true
复制代码

实例和原型之间是通过__proto__属性连接,且是单向的,从实例指向原型原型和构造函数之间连接是双向的,通过constructor和prototype连接,具体见图;原型链上的属性是所有实例共享的,看下面的例子:

var A = function(){
    this.name="xiaoming";
}
var a = new A();
A.prototype.age=9;
var b = new A();
console.log(a.age); //9
console.log(b.age); //9
复制代码

a、b都可以访问A原型链上的属性age。

Function和Object比较特殊,他们既是对象又是函数,两者内部同时含有proto和prototype属性,可看下面代码:

Object.__proto__ === Function.prototype //true
Object.__proto__ === Function.__proto__//true
Object.prototype === Function.prototype.__proto__ // true
Function instanceof Object //true
Object instanceof Function //true
复制代码

至此,原型链的知识差不多可以理解了,后面介绍继承的几种方式。

原型链继承

既然可以访问原型链的所有属性,那么就可以用原型链的原理实现继承。原型链继承用new的方式(实现A继承B):
A.prototype=new B();关于new可以看下我另一篇文章this那些事

代码:

function B(){
    this.nameB=‘B‘;
}
B.prototype.nameProto="PROTO";
function A(){
    this.nameA="A";
}
A.prototype=new B(); //原型链继承:A继承B
var a=new A();
console.log(a);
复制代码

打印结果:

技术分享图片
上段代码A继承B,通过A构造函数new的示例a不仅可以继承B(可访问nameB),而且可以继承B原型上的属性(nameProto),且是所有实例共享的。

好处:可以继承原型链的属性
缺点:无法实现多继承,A继承了B,就无法再继承C

构造继承

构造继承就是利用构造函数继承,即改变this指向的方式(call/apply/bind)执行一次构造函数B,具体可我另一篇文章this那些事。废话不多说,上例子:

function B(){
    this.nameB=‘B‘;
}
B.prototype.nameProto="PROTO";
function A(){
    B.call(this); //A继承B,只举了call的例子,apply、bind类似
    this.nameA="A";
}
var a=new A();
console.log(a);
复制代码

打印结果:

 

技术分享图片
根据a的打印结果,我们看到nameB和nameA是同一层级,虽然实现了A继承B,但是通过a的结构看不出来,而且无法继承B原型链上的属性nameProto,不过它的好处是可以多继承,可以通过C.call(this)继承C。

 

好处:可以多继承
缺点:无法继承原型链上的属性

组合继承

组合继承就是为了解决原型链继承无法多继承、构造继承无法继承原型链上的属性的问题而诞生的,将两种方式结合。

function B(){
    this.nameB=‘B‘;
}
B.prototype.nameProto="PROTO";
function A(){
    B.call(this); //构造继承
    this.nameA="A";
}
A.prototype=new B(); //原型链继承:A继承B
var a=new A();
console.log(a);
复制代码

打印结果:

技术分享图片
观察a的打印结果,似乎真的解决了上述两个问题,它也引入了一个新的问题:nameB属性有两个,这样造成了资源浪费(存储占用内存)。

 

原型式继承

先看下面的示例:

function objectCreate(obj){
  function F(){};
  F.prototype = obj;
  return new F();
}
var a=objectCreate(A.prototype);


 
 

 






以上是关于js 原型链与继承的主要内容,如果未能解决你的问题,请参考以下文章

Js基础知识 - 原型链与继承精彩的讲解

js 原型链与原型

JavaScript难点系列:原型链与继承

js原型链与lua元表的异同?

原型链与继承

原型链与继承