推敲js的原型和原型链

361 阅读3分钟

首先提出问题,什么是原型和原型链,作用是什么?
这是我自己总结出来的回答:
每个对象都有其对应的原型,可以通过对象.__proto__来获取原型,获取到的就是其构造方法的原型对象,然而获取构造函数的原型对象的方式是通过构造函数.prototype,所以一般实例对象的__proto__就会等于构造函数的prototype,这个相互连接而成的链路就是原型链,当我们在对象上找不到方法或者属性的时候就会顺着原型链去父级原型上找,原型的作用就是为了对象共享属性和方法。

这里面包含了许多概念,比如原型,原型对象,原型链,构造函数,prototype和__proto__,等等 可以上一张图

image.png

下面就根据这个图说一下我的理解,但是在此之前还需要讲解一个知识点,因为js万物皆对象,所以对象又分为实例对象函数对象

先说结论:凡是通过 new Function() 创建的对象都是函数对象,其他的都是普通对象,可以用一段代码说明

var o1 = {}; 
var o2 =new Object();
var o3 = new f1();

function f1(){}; 
var f2 = function(){};
var f3 = new Function('str','console.log(str)');

console.log(typeof Object); //function 
console.log(typeof Function); //function  

console.log(typeof f1); //function 
console.log(typeof f2); //function 
console.log(typeof f3); //function   

console.log(typeof o1); //object 
console.log(typeof o2); //object 
console.log(typeof o3); //object

在上面的例子中 o1 o2 o3 为普通对象,f1 f2 f3 为函数对象,为什么Object和Function也是函数对象呢,因为Object和Function是构造函数,是通过new Function()来创建的。

正文开始:
1、原型:js中每个对象都能找到它所对应的原型对象,这里所说的是找到,那么就可以将这个原型对象称为对象的原型,可以通过__proto__来获取。
2、原型对象:是函数对象所对应的一个对象,一般的函数是一个空对象,但是Function()这个函数的原型对象上就放在所有函数的内置方法,例如call(), apply(), bind()等,因为所有函数都是都给这个Function()构造出来的。原型对象可以通过prototype来获取

注意:js的函数对象和实例对象都有原型__proto__,但是原型对象prototype只有函数的对象有

根据上图可以得出:
1、实例对象的原型等于构造函数的原型对象也就是 let f = new Fun(); 那么 f.__proto__ === Fun.prototype 成立
2、任何函数的原型都是Function原型对象,即任何函数.__proto__ === Function.prototype
3、任何函数都有一个独立的原型对象,是一个空对象,这个对象的原型就是终点对象,即任何函数.prototype.__proto__ === Object.prototype
4、任何函数能调用的方法(内置方法)都是存在Function原型对象上,所以任何函数都能共享这些方法
5、任何函数new出来的对象,他的原型都是指向构造函数的原型对象上,既.prototype上,如果这个原型对象没有该属性或者方法,那么就会顺着原型链找到了Object的原型对象(任何函数.prototype.__proto__),既Object.prototype,如果这个Object.prototype也没有就会继续通过.__proto__往上找,但是Object.prototype.__proto__为null了,所以查找结束

上述是本人推敲过程中结合上图得出的一些理解,最终得出开头的那段结论