记阿里四面的一道有关原型链的面试题
Function.prototype.a = 'a'; Object.prototype.b = 'b'; function Person(){}; var p = new Person();
问:p是否可以访问到 a 和 b ?
这个问题在阿里四面的时候被面试官问到,当时对于原型链的了解并不是很深入,所以被问到之后一脸懵QAQ。
今天在刷题时又遇到了相似问题,于是乎决定仔细研究一下这个问题。
- 首先来看一下JS高设中对prototype的描述。
对于 ECMAScript 中的引用类型而言,prototype 是保存它们所有实例方法的真正所在。
我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象, 而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那 么 prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。
在我的理解中,prototype就是我们所创建对象基于的对象的属性和方法。
- 在讲解prototpye我们先了解一下__proto__的概念:
__proto__是一个指针,它指的是构造它的对象的对象的prototype。
是不是有些晦涩,举例说明。
我们首先新建一个变量,并赋值为1。
var a = 1 其实等价于 var a = new Number(1),所以 a 是一个Number类型。
我们打印一下 a 的 proto,可以看到我们打印出来了a的构造对象Number的prototype。
所以 __proto__是一个指向其构造对象的prototype的指针,如 a 的 proto 指向了Number的prototype。
同样是这个例子,打印a._proto__可以看到Number的prototype,即Number的属性及方法。
-
那么问题来了,原型链有什么作用呢?
我们通过上图可以看到,Number对象的直接prototype是没有toLocaleString()方法的,但实际上a 仍然可以调用toLocaleString()方法,这就是原型链的作用。在JS中,万物皆对象。我们可以看到Number对象的_proto__指向了Object,而Object拥有toLocaleString()方法。这就是原型链的作用。
题解直达
好了,言归正传。
Function.prototype.a = 'a';
Object.prototype.b = 'b';
function Person(){};
var p = new Person();
问:p是否可以访问到 a 和 b ?
这道题的答案是:p可以访问到 b ,但无法访问到 a;
首先我们可以确定的是,p为Person的一个实例,我们打印发现Person的类型是Object,所以 p 的_proto__实际上指向的是Person的prototype,而Person_proto__指向Object的prototype,因此p可以访问到b,但无法访问到 a 。
那么接下来的代码,控制台会打印什么呢
Function.prototype.a = 'a';
Object.prototype.b = 'b';
var person = new Function();
person.prototype.c = 'c';
var p = new person();
console.log(p.c); // c
如果给Person的prototype加一个c属性,p是否可以访问到呢?答案是可以访问到。
因为p为Person的实例,即p的_proto__指向Person的prototype,自然是可以访问到c的。
如有错误欢迎指正QvQ~