前端面试必问——JS中的原型(prototype)、原型链和继承

原型、原型链与原型继承也是一个老生常谈的问题了,可以说js原型弄明白了,那么学习js就得了一种质的飞跃,今天我们就来看看这个在前端面试中的高频考题究竟是怎么一回事。


一、原型

前端面试必问——JS中的原型(prototype)、原型链和继承_第1张图片

要说原型,我画了上面那张图,它生动的表达了js中的构造函数、实例对象以及原型对象的关系:

  • 每个对象都有_proto_属性,并且指向它的原型对象
  • 每个构造函数都有它的prototype原型对象
  •  prototype原型对象里的constructor指向它的构造函数
  • new一个构造函数会形成它的实例对象

如果光看文字并不能理解清楚的同学我们可以来看一段代码:

function Person(name,age){
     this.name=name;
     this.age=age;
}

var p1=new Person('小满',18);
var p2=new Person('大雪',20);
        
console.log(p1,p2)
console.log(Person.prototype);
console.log(p1.__proto__);

console.log(p1.__proto__===Person.prototype);
console.log(p2.__proto__===Person.prototype);
console.log(p1.__proto__===p2.__proto__);

console.log(p1.__proto__.constructor);
console.log(Person.prototype.constructor);

这段代码的输出结果如下:

前端面试必问——JS中的原型(prototype)、原型链和继承_第2张图片

由上述代码我们不难看出,prototype原型对象是一个公共容器 ,特定类型所有实例对象都可以访问。

二、原型链

什么是原型链?从概念上来看:每个对象都可以有一个原型_proto_,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了。

每个对象都可以有一个原型,这个原型还可以有它自己的原型,以此类推,形成一个原型链。

那么什么时候会用到原型链呢?

当我们查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去原型对象的原型对象里去寻找...... 这个操作就是被委托在整个原型链上。

如果没找到,会一直找下去吗?

先说结论:原型链是有终点的,不会一直找下去。当Object.prototype.__proto__ === null时,查找结束,返回undefined。


举例

我们还是通过一个例子来看:

var num=[1,2];        
console.log(num);
console.log(num.__proto__.__proto__)

我们想要从这个对象中找到valueOf()方法,我们先来看看这个对象本身:

前端面试必问——JS中的原型(prototype)、原型链和继承_第3张图片

按照理论如果对象里没有我们就去它的原型对象里找,那么我们看看它的原型对象:

前端面试必问——JS中的原型(prototype)、原型链和继承_第4张图片

经过查找发现依然没有,那么我们再去原型对象的原型对象里查找:

前端面试必问——JS中的原型(prototype)、原型链和继承_第5张图片

这个时候我们终于找到了这个valueOf方法。

由此我们可以看出整个查找过程:

如果最后依然没有找到的话,那么就是下面这样的:

三、原型链继承

看完上面那些再来说原型链的继承就简单了很多。

首先,来看看什么是继承?

继承是指一个对象直接使用另外一个对象的属性和方法

1、 那么我们先来看属性是如何继承的。

先创建一个Person类:

        function Person(name,age){
            this.name=name;
            this.age=age;
        }

然后创建一个Student类,让它继承Person类的属性,并且添加一个 subject属性:

        function Student(name,age,subject){
            this.name=name;
            this.age=age;
            this.subject=subject;
        }

属性的继承就是通过圈起来的部分实现的:

前端面试必问——JS中的原型(prototype)、原型链和继承_第6张图片

然后我们实例化一下:

var s1=new Student('明明',6,'math');
console.log(s1.name,s1.age,s1.subject);

此时Student就已经成功继承了Person的属性。

1、 来看方法是如何继承的。

我们依然先创建一个Person类,并且将方法定义在构造函数的原型上。

        function Person(name,age){
            this.name=name;
            this.age=age;
        }
        Person.prototype.study=function(){
            console.log("学习")
        } 

 紧接着创建一个Student类,并让Student.prototype=new Person(),最后实例化一下

        function Student(name,age,subject){
            this.name=name;
            this.age=age;
            this.subject=subject;
        }

        Student.prototype=new Person();
        var s1=new Student('明明',6,'math');
        console.log(s1.name,s1.age,s1.subject);
        s1.study();

结果如下图所示,很明显Student类以及继承了Person的方法。

这里方法的继承就是通过: 这句代码来实现的。

四、尾声

说到这里呢,原型和原型链以及原型链的继承差不多就说完了,想要更加深入的理解可以进一步学习js中的对象类型以及不同的继承方法。


欢迎各位大佬指正,如果觉得不错就点个赞吧

你可能感兴趣的:(前端,#,js)