网站首页 > 技术文章 正文
JS原型链是前端面试中的经典问题了,几乎所有前端面试或笔试都会考察应聘者对原型链的理解程度,同时这一块知识点也是JavaScript中的一个重点和难点。因为之前看红宝书JavaScript高级程序设计感觉里面讲的不是很透彻,所以今天就打算重新梳理总结一下。
首先,读者可以通过下图自我检测一下是否真正理解原型链:
如果看图能完全理解里面每一个箭头的,可以不用继续往下看了,你已经基本掌握原型链了;如果看图感觉箭头绕来绕去很复杂,也不用慌,看完这篇文章,你就能完全理解这张图了。
1.隐形原型和显性原型
在讲原型链之前,我们需要知道隐形原型(__proto__)和显性原型(prototype)这两个概念。
prototype
prototype属性,它是函数所独有的,它是指向函数的原型对象的一个指针,这个对象的用途就是包含所有实例对象共享的属性和方法(我们把这个对象叫做原型对象);
示例:
function Foo(){ } Foo.prototype.name="martin"; let f1=new Foo(); let f2=new Foo(); console.log(f1.name); //martin console.log(f2.name); //martin
可以看出,Foo函数原型对象上的属性和方法被每个实例所共享。
__proto__
__proto__ 是原型链查询的关键属性,它是指向对象构造函数原型对象的一个指针,它是对象独有的。
注意:函数中也有__proto__属性,因为函数是特殊的对象。?
function Foo(){ } Foo.prototype.name="martin"; let f1=new Foo(); console.log(f1.__proto__ === Foo.prototype); //true
其中Foo是f1的构造函数,所以f1的隐形原型指向的是Foo的原型对象。
2.什么是原型链
每个对象都有一个隐形原型 __proto__ 属性,里面存的是一个指针,指针指向该对象构造函数的原型对象,而该原型对象也有一个__proto__属性,里面也存着一个指针,该指针指向该对象的构造函数的原型对象,通过这种方式形成了一条向上寻找的链条,这个链条就叫做原型链。
示例:
function Foo(){ } let f1=new Foo(); console.log(f1.__proto__ === Foo.prototype); //true console.log(Foo.prototype.__proto__===Object.prototype); //true console.log(Object.prototype.__proto__===null); //true
其中f1的隐形原型指向其构造函数Foo的原型对象,且Foo原型对象的构造函数为内置构造函数Object(所有对象的基础构造函数),因此Foo.prototype的隐形原型指向Object的原型对象,最后Object.prototype的隐形原型指向null(这个指向记住就好,底层代码规定好的),这就是一条完整的原型链了,如下图:
3.关键指向要记住
在内置的函数和原型对象中,有几个关键指向或者说是容易混淆的指向我们要记住。
- Function.__proto__===Function.prototype,也就是Function内置函数(所有函数的基础构造函数)的构造函数是它自己,因此隐形原型指向自己的原型对象
- Object.__proto__===Function.prototype,这个很好理解,Object是对象的基本构造函数,毕竟它也是一个函数,因此它的构造函数就是Function了。
- Object.prototype.__proto__===null,也就是说Object.prototype的隐形原型是null,但是要注意的是,这里并不代表Object.prototype的构造函数是null,但是说明null是原型链的顶端,这其实是JS一直以来的一个Bug,记住就行。
4.原型链的查找
原型链的查找其实就是通过隐形原型(__proto__)连接的各个对象构造函数的原型对象(prototype),从而去查找原型链上各个原型对象上是否存在查找的属性或者方法,那原型链的具体查找顺序又是如何呢?
原型链的查找顺序
先找实例对象中是否有查找的属性或方法,若有则直接返回,没有则一步步沿着原型链在上层的原型对象中查找。
示例:
function life() { } life.prototype.name="martin"; function person(){ } person.prototype=new life(); person.prototype.constructor=person; let student=new person(); console.log(student.name); //martin
这个例子中的实例student的name属性查找顺序如下图所示:
先查找student实例,发现没有name属性,则向原型链上一person.prototype对象中查找,发现也没有,则继续向上一层的life.prototype对象中查找,发现有name属性,则直接返回name的属性值并停止原型链的查找。
5.自测题
下面可以做几个自测题检验一下自己是否理解,如果不理解请再多看几遍文章开头的图。
A instanceof B是用来检测B的原型对象(B.prototype)是否在A的原型链上,如果存在返回true。
console.log(Function instanceof Function); console.log(Function instanceof Object); console.log(Object instanceof Object); console.log(Object instanceof Function);
- Function instanceof Function即Function.prototype是否在Function的原型链上
返回true
- Function instanceof Object即Object.prototype是否在Function的原型链上
返回true
- Object instanceof Object即Object.prototype是否在Object的原型链上
返回true
- Object instanceof Function即Function.prototype是否在Object的原型链上
返回true
猜你喜欢
- 2024-11-10 这样理解 JS 原型链,通透 js原型链的理解
- 2024-11-10 JavaScript-原型链 javascript 原型,原型链 ? 有什么特点?
- 2024-11-10 javascript原型链 js原型链的用处
- 2024-11-10 js 原型/原型链/构造函数/实例/继承
- 2024-11-10 【JavaScript 高级】深入了解原型链
- 2024-11-10 快速读懂JavaScript中的原型链 js的原型和原型链是什么
- 2024-11-10 你可能不太理解的JavaScript - 原型与原型链
- 2024-11-10 我在jacascript中学习到的那些原型链,你知道吗?
- 2024-11-10 JavaScript中的原型prototype和__proto__的区别及原型链概念
- 2024-11-10 面试问题分享 - 5:解释一下 原型、构造函、实例、原型链 之间的关系
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-