原型、原型链与原型继承也是一个老生常谈的问题了,可以说js原型弄明白了,那么学习js就得了一种质的飞跃,今天我们就来看看这个在前端面试中的高频考题究竟是怎么一回事。
一、原型
要说原型,我画了上面那张图,它生动的表达了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);
这段代码的输出结果如下:
由上述代码我们不难看出,prototype原型对象是一个公共容器 ,特定类型所有实例对象都可以访问。
二、原型链
什么是原型链?从概念上来看:
每个对象都可以有一个原型,这个原型还可以有它自己的原型,以此类推,形成一个原型链。
那么什么时候会用到原型链呢?
当我们查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去原型对象的原型对象里去寻找...... 这个操作就是被委托在整个原型链上。
如果没找到,会一直找下去吗?
先说结论:原型链是有终点的,不会一直找下去。当Object.prototype.__proto__ === null时,查找结束,返回undefined。
举例
我们还是通过一个例子来看:
var num=[1,2];
console.log(num);
console.log(num.__proto__.__proto__)
我们想要从这个对象中找到valueOf()方法,我们先来看看这个对象本身:
按照理论如果对象里没有我们就去它的原型对象里找,那么我们看看它的原型对象:
经过查找发现依然没有,那么我们再去原型对象的原型对象里查找:
这个时候我们终于找到了这个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;
}
属性的继承就是通过圈起来的部分实现的:
然后我们实例化一下:
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中的对象类型以及不同的继承方法。
欢迎各位大佬指正,如果觉得不错就点个赞吧👍