面试官: 讲讲什么是原型链吧
前言
讲Javascript原型
和原型链
的文章数不胜数,但能让读者读懂的真的是少之又少。而作为面试常考的知识点之一,我们都应该知道原型和原型链的重要性。为了理解原型和原型链,我先前也看过非常多的文章,网上相关的优质文章真的是非常少,本文我会用自己的理解再结合网上一些大牛的文章来向你描述原型和原型链是什么,包你弄懂原型和原型链!
什么是原型和原型链?
当面试官问到这个问题,我们该怎么回答? 这里先给个标准答案
:
在Javascript中我们通常都是用构造函数
来新建一个对象
的,每一个构造函数内部都有一个prototype
属性值,这个属性值是一个对象,这个对象(也称为原型对象)包含了由该构造函数创造出所有实例所共享的属性和方法。当我们用构造函数创建了一个新对象
,这个新对象内部会有一个的指针,这个指针被称为对象的原型
,一般来说我们是不能够获取到这个指针
的,但是现在浏览器中我们都可以用__proto__属性让我们获取到这个指针。
当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象
里找这个属性,这个原型对象又会有自己的原型
,于是就这样一直找下去,也就是原型链
的概念。原型链的尽头一般来说都是Object.prototype,而Object.prototype的原型指向null,所以这就是我们新建的对象为什么能够使用 toString() 等方法的原因。
一图胜千言(以下问题都是结合此图分析)
注意 : 图中一共有3个构造函数,分别是Foo、Object、Function。
让我们从上往下看 :
首先看到 Foo构造函数
有一个 prototype属性
指向一个对象(之前说过这个原型对象
是包含了创建出所有实例共享的原型和方法的)。注意原型对象上面还有一个constructor指回函数Foo。再看到f1和f2
是两个对象,它是由Foo构造函数new出来的,而f1、f2对象中都有一个__proto__
指针(我们称之为原型)指向Foo.prototype
。
可以试着在控制台打印一下以下代码验证是不是真的是这样的:
function Foo(){}
Foo.prototype.a = 'b'
var f1 = new Foo()
var f2 = new Foo()
console.log(Foo.prototype)
console.log(Foo.prototype.constructor)
console.log(f1.__proto__)
console.log(f2.__proto__)
复制代码
注意:每一个构造函数和它创建出来的对象的关系都是这样子的(除非我们手动修改它们内部的值),明白了吗?没明白的话可以多看几遍。(可以仔细观察图中的Foo、Object、Function构造函数也都是这样的)
疑问一:怎么Foo.prototype也有一个__proto__指针?
是的,每一个prototype
也会有一个__proto__指针,指向下一个原型,一般来说,终点都是Object.prototype,而Object.prototype的__proto__指向null,原型链就结束了。
知道javascript的继承
吗?经常用的组合继承和寄生式组合继承
的原理其实就是改变构造函数的prototype改变原型链实现继承的,原型链改变了,创建出来的实例的属性肯定就改变了呀,从而实现了继承。对继承不太懂的朋友可以看看我写的这篇文章 :
javascript中的五大继承
疑问二:怎么构造函数Foo也有__proto__指针?
函数它也是一个对象呀,它的构造函数是function Function(),这下你明白为什么它也有__proto__指向Function.prototype了吧?
补充 instanceOf 原理
还是拿图一说 f1 instanceof Object
会是true吗
instanceof原理其实就是看看Object.prototype
是否存在于f1的原型链
中,顺着__proto__
找,明显是存在的,所以返回的结果就是true啦。
完结
相信大家已经搞懂了原型和原型链了吧。如果还有不懂的地方可以评论哈。
撰文不易,觉得文章写的还不错的可以点个赞哦!你们的支持是我创作的最大动力!