今天的面试题是一道关于原型链的易错面试题。
在开始之前呢,我们先要知道。原型链中查找是按照原型链查找的,如果在自己身上就有那个值,那么就直接取那个值,没有的话就往上查找。直到找到,如果没有就返回undefined
。
陷阱:
如果自身是this
那么new
出来的肯定就有那个值,但是自身的是普通的声明变量。那么就要往上面查找直到找到为止。
在这里我们要明白在原型上面添加值,第一种是通过this
指向添加
第二种是通过x.prototype
直接添加到原型上。
第三种通过方法劫持也可以
简简单单先来第一道简单的面试题:
function A() {
this.do = function () { return 'foo'; };
}
A.prototype = function () {
this.do = function () { return 'bar' };
};
var x = new A().do();
console.log(x);//foo
在这道题目中两个构造函数中都是直接使用的this
去点的,所以按照上面我说的法则,调用的是她自身的do
。这里的A.prototype
就没用了。这里找的x
就是查找A
构造函数中的值就是foo
上面那道题算简单的。
下面我们简简单单再来一刀4399的面试题
var A = { n: 4399 };
var B = function () { this.n = 9999 };
var C = function () { var n = 8888 };
B.prototype = A;
C.prototype = A;
var b = new B();
var c = new C();
A.n++;
console.log(b.n);
console.log(c.n);
下图种的n=8888应该是没有的,画图笔误
上面是简单画的一个图。
我说明一下整个代码块的运行:
此题中主要的一个陷阱:自身的变量是否在原型上面是否能被new
出来的对象点到。上面规则中提到过。这里的B
中的n
是被定义在自身的原型上面的,new
出来的对象是可以把n
点到的。但是C
中的n
是普通的一个的变量声明通过上面我所说的添加方法这里的普通变量肯定没有在原型链上面
后面B
C
的原型都是指向A
的
创建对象B
C
时,B
中的有this
此时new
出来的对象可以直接调用这个this
指向的n
值,b.n
就是9999
创建对象C
因为C
自身的n
是一个普通的声明变量,也不能被new
出来的对象点到,简单点说就是,8888根本就没有在new
出来的对象上面。根本就点不到。按照原型链的规则,要往上面查找,最后就查找到了4399+1==4400;
若有问题请指出,我即使改正。麻烦各位大佬!