一道面试题:
function Foo() {
Foo.a = function () {console.log(1)};
this.a = function () {console.log(2)};
}
Foo.prototype.a = function () {console.log(3)};
Function.prototype.a = function () {console.log(4)};
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();
输出结果为
4
2
1
结合原型链回看此题目
沿着原型链向上寻找 是通过 __proto__ 属性完成的,在使用 new 关键字时,会执行一步 obj.__proto__ = Foo.prototype 来绑定原型对象。
第一个 Foo.a():由于此时 Foo 未被执行 函数内的Foo.a还未被调用;我对原型链的理解不深, Foo.prototype.a 误导了我的思维,以为会从原型链向上找到 Foo.prototype.a。
其实 Foo.prototype.a 会影响 let obj = new Foo(); 但是obj中有a属性,所以并不会沿着原型链向上找 Foo.prototype.a;
而 Foo.a 则会被 Function.prototype.a 影响(function关键字类似于一个语法糖?由Function构造函数创建,所以 Foo.__proto__ 指向 Function.prototype),当 Foo 中找不到 a 属性时,会沿着原型链向上找到 Function.prototype 中的 a;所以第一个Foo.a() 输出 4;
第二个 obj.a(); 是2
最后一个 Foo.a() ; 发生在 Foo() 执行之后,Foo.a = function... 已经被执行,所以其输出 1(js中一切皆为对象,function也是对象)