function F(){ function C(){ return this;}; return C(); } var a = new F(); alert(a == window);
通过对函数调用机制的学习,可以分析出上面变态笔试题的答案。
首先,函数调用有四种方式,主要是this的指向,然后return的方式
1. The Method Invocation Pattern,当函数为一个对象的属性时,此时的this指向的就是该对象
var myObject = { value:10, double:function(){ return this.value *= 2; } } alert(myObject.double());
2. The Function Invocation Pattern,当函数不是任何对象的属性时,此时的this指向的是global object,浏览器中是window
错误实例:
var myObject = { value:10, getValue:function(){return this.value;} } myObject.double = function(){ var multi = function(times){ //打开注解查看this值 //alert(this.value);//undefined //alert(this);//object //alert(this == window);//true return this.value *= times; } multi(this.value); } myObject.double(); alert(myObject.getValue());//10
对上述错误实例进行修改:
var myObject = { value:10, getValue:function(){return this.value;} } myObject.double = function(){ var thisObject = this; var multi = function(times){ return thisObject.value *= times; } multi(this.value); } myObject.double(); alert(myObject.getValue());//100
3. The Constructor Invocation Pattern,构造函数式的函数调用,this指向的是新创建的对象,使用new前缀的方式调用函数,会创建一个新对象,这个新对象有一个隐藏的链接指向该函数的prototype成员。
这种调用方式会改变return的行为:只要 new 表达式之后的 constructor 返回(return)一个引用对象(数组,对象,函数等),都将覆盖new创建的匿名对象,如果返回(return)一个原始类型(无 return 时其实为 return 原始类型 undefined),那么就返回 new 创建的匿名对象。
当使用第二种方式(The Function Invocation Pattern)调用构造函数时,会产生莫名其妙的问题
var House = function(add){ this.address = add; } House.prototype.getAdd= function(){ return this.address; }; var myHouse = new House("Beijing"); var err = House("Heaven"); alert(err);//undefined alert(myHouse.getAdd());//Beijing
如果在构造函数中return另一个对象,此时会丢掉new语义所生成的新对象
var House = function(add){ this.address = add; return new Date(); } House.prototype.getAdd= function(){ return this.address; }; var myHouse = new House("Beijing"); alert(myHouse.getAdd);//undefined alert(myHouse);//当前时间
4. The Apply Invocation Pattern,使用函数的apply方法,可以自定义this值
现在,我们可以清晰的分析开头提出的问题:
a. C()采用的是第二种方式调用,所以C函数中的this指向的是global object,此处就是window
b. var a = new F();是采用的第三种方式调用,并且return了一个对象,此时相当于采用的是第二种调用方式,所以a的值为C()返回的值,即window
c. 结论:这个问题输出的是true