赋料扬雄敌,诗看子建亲。这篇文章主要讲述#yyds干货盘点#JavaScript之彻底理解原型与原型链相关的知识,希望能为你提供帮助。
前言原型与原型链知识历来都是面试中考察的重点,说难不算太难,但要完全理解还是得下一定的功夫。先来看一道面试题开开胃口吧:
function User()
User.prototype.sayHello = function()
var u1 = new User();
var u2 = new User();
console.log(u1.sayHello === u2.sayHello);
console.log(User.prototype.constructor);
console.log(User.prototype === Function.prototype);
console.log(User.__proto__ === Function.prototype);
console.log(User.__proto__ === Function.__proto__);
console.log(u1.__proto__ === u2.__proto__);
console.log(u1.__proto__ === User.__proto__);
console.log(Function.__proto__ === Object.__proto__);
console.log(Function.prototype.__proto__ === Object.prototype.__proto__);
console.log(Function.prototype.__proto__ === Object.prototype);
基础铺垫
javascript
所有的对象本质上都是通过new 函数
创建的,包括对象字面量的形式定义对象(相当于new Object()
的语法糖)。
文章图片
- 所有的函数本质上都是通过
new Function
创建的,包括Object
、Array
等
文章图片
- 所有的函数都是对象。
prototype
每个函数都有一个属性prototype
,它就是原型,默认情况下它是一个普通Object
对象,这个对象是调用该构造函数所创建的实例的原型。文章图片
contructor属性
javaScript
同样存在由原型指向构造函数的属性:constructor
,即Func.prototype.constructor --&
gt;
Func
文章图片
__proto__
JavaScript
中所有对象(除了null
)都具有一个__proto__
属性,该属性指向该对象的原型。function User()
var u1 = new User();
// u1.__proto__ ->
User.prototype
console.log(u1.__proto__ === User.prototype) // true
显而易见,实例的
__proto__
属性指向了构造函数的原型,那么多个实例的__proto__
会指向同一个原型吗?var u2 = new User();
console.log(u1.__proto__ === u2.__proto__) // true
如果多个实例的
__proto__
都指向构造函数的原型,那么实例如果能通过一种方式,访问原型上的方法,属性等,就可以在原型进行编程,实现继承的效果。我们继续更新一下原型与原型链的关系图:
文章图片
原型链实例对象在查找属性时,如果查找不到,就会沿着
__proto__
去与对象关联的原型上查找,如果还查找不到,就去找原型的原型,直至查到最顶层,这也就是原型链的概念。就借助面试题,举几个原型链的例子:
举例
u1.sayHello()
:u1
上是没有sayHello
方法的,因此访问u1.__proto__(User.prototype)
,成功访问到sayHello
方法u2.toString()
u2,User.prototype
都没有toString
方法,User.prototype
也是一个普通对象,因此继续寻找User.prototype.__proto__(Object.prototype)
,成功调用到toString
方法
function A()
function B(a)
this.a = a;
function C(a)
if (a)
this.a = a;
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
console.log(new A().a);
//1
console.log(new B().a);
//undefined
console.log(new C(2).a);
//2
但距离解决文章的最初的面试题还欠缺些什么,比如
Function.__proto__ === Object.__proto__、Function.prototype.__proto__ === Object.prototype.__proto__
等,接着我们来一一攻克它。Objcet.__proto__
、 Object.prototype
、Object.prototype.__proto__
Object
是构造函数,在第二部分我们讲过所有的函数都是通过new Function
创建了,因此Object
相当于Function
的实例,即Object.__proto__ --& gt; Function.prototype
。
Object.prototype
是Object
构造函数的原型,处于原型链的顶端,Object.prototype.__proto__
已经没有可以指向的上层原型,因此其值为null
// 总结:
Object.__proto__ -->
Function.prototype
Object.prototype.__proto__ -->
null
Function.__proto__
、Function.prototype
、Function.prototype.__proto__
Function.prototype
是Function
的原型,是所有函数实例的原型,例如上面讲的Object.__proto__
Function.prototype
是一个普通对象,因此Function.prototype.__proto__ --& gt; Object.prototype
Function.__proto__
:__proto__
指向创造它的构造函数的原型,那谁创造了Function
那?
- 猜想:函数对象也是对象,那
Function.__proto__
会指向Object.prototype
吗?上文提到,Object.__proto__ --& gt; Function.prototype
。如果Function.__proto__ -& gt; Object.prototype
,感觉总是怪怪的,到底谁创造了谁,于是我去做了一下测试:
文章图片
实践证明只存在Object.__proto__ --& gt; Function.prototype
- 苦思冥想没得出结果,难道
Function
函数是猴子不成,从石头缝里面蹦出来的?于是我进行了一同乱七八糟的测试,没想到找出了端倪。
文章图片
通过上面我们可以得出:Function.__proto__ --& gt; Function.prototype
- 猜想:函数对象也是对象,那
最后再附赠个简单的面试题,提高一下自信:
var F = function ()
Object.prototype.a = function ()
Function.prototype.b = function () var f = new F();
console.log(f.a, f.b, F.a, F.b);
// 原型链
// f.__proto__ -->
F.prototype -->
Object.prototype
// F.__proto__ -->
Function.prototype -->
Object.prototype
推荐阅读
- #yyds干货盘点#Vue-Router路由所有相关方法讲解(全),实战教学含登录拦截,建议收藏
- #yyds干货盘点# InnoDB解决幻读的方案--LBCC&MVCC
- 迁移到新的Web主机后显示的WordPress模板
- 自定义帖子类型的WordPress模板层次结构
- WordPress模板分配未按预期工作
- WordPress Style.css标头错误
- 具有和或条件的WordPress分类法查询
- WordPress的分类术语还包含仪表板页面吗()
- 分页存档页面上的WordPress粘帖