从一个例子看JS函数调用

198 阅读2分钟

深圳每年这个时候的大雨,都爱赶早高峰。今天下的也是好大,平时走路上班,今天过河。。。

sad...

出门换上了拖鞋,还犹豫了下要不要换短裤,后来怕在公司冷就又穿上了牛仔裤,然后裤子湿到了大腿根。。。。

sad...

休息时,看到一道面试题,兴冲冲的做一下,竟然做错了一半。。。

sad...

一天下来,sad三连,也太惨了吧。我要做点什么弥补一下,那就好好总结下这道面试题的知识点喽。

以上废话结束,面试题登场:

var a = function () {this.b = 3;}
var c = new a();
a.prototype.b = 9;
var b = 7;
a();

console.log(b);
console.log(c.b);

这个题的正确答案都是3,而我答成了3和9。

先来看第一个输出3,先变量提升,之后b被赋值为7,但是接着后面调用了a(),这里默认是window调用的a,所以this指的就是window,而b是全局变量,所以是3。这是非严格模式下,如果是严格模式,结果就是undefined。因为严格模式下,this不能给默认值的。

再来看第二个输出。这里用new的方式,调用了a。用new的方式调用,会自动创建一个prototype给调用者,这里也就是c。并且这个c.prototype指向a.prototype的值。当给a.prototype.b赋值为9时,通过c.prototype.b获得的也是同一个9。而c.b是执行函数a()后得到的,function里的this就是c,所以c.b为3。

这里主要要明确的是:new只是个函数的调用方式,与java里的new一个对象不同,后者是复制一个长得相同的对象,而前者则是做一个关联。new的同时,会给调用者创建一个prototype对象,这个对象关联到被调用者的prototype上,使他们对应的是同一个值。

被调用者(本例中的a)的prototype上还会在一开始被添加一个constructor的属性,这个属性是共有的且不可枚举。这个属性引用的是对象关联的函数(本例中是a)。c.prototype.constructor