JavaScript中Apply调用模式的this指向

关于apply第一个参数指定了函数体内this对象的指向,我之前的理解是:

  A.apply(x,array);表明x调用函数A并传入参数数组array,即类似x.A(array[0],array[1]...),所以这样就很像方法调用模式很容易理解函数A内的this指向了x,即指定了函数体内this对象的指向。

这里有我第一个疑问:apply的第一个参数指定了函数体内this对象的指向就是这个意思吗?但这样理解挺麻烦的,好像不如直接无脑的想把第一个参数绑定到了函数的this上。

我的第二个疑问是最近看到了一段代码:

var getSingle=function(fn){
    var ret;
    return function(){
        return ret || (ret=fn.apply(this,arguments));
    }
};
var getScript=getSingle(function(){
    return document.createElement("script");
});
var script1=getScript();
var script2=getScript();
alert(script1===script2);//true

var script3=window.document.createElement("script");
alert(script2===script3);//false???

这是我对这段代码的理解:

首先查了一下相关概念:每个函数在被调用时都会自动取得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此在闭包中不可能直接访问到外部函数中的这两个变量。

执行var script1=getScript();相当于

var script1=getSingle(function(){
    return document.createElement("script");
})();

此时属于函数调用模式,getSingle()函数内this指向了window,然后getSingle函数内的闭包

return function(){
    return ret || (ret=fn.apply(this,arguments));
};

此时立即被调用,所以闭包中的

ret=fn.apply(this,arguments);也就是

ret=(function(){
    return document.createElement("script");
}).apply(this,arguments)

这个apply里的this因为闭包立刻被调用执行所以也属于函数调用模式,进而也就指向了window。

然后这里就出现了我的第二个疑问,即

但如果按我之前的理解就类似于下面这种奇奇gaygay的东西

ret=~window.(function(arguments){
    return document.createElement("script");
})=document.createElement("script");

所以我之前的理解只是适合方法调用模式。这里.apply(window,arguments)是不是直接可以不管了?就是默认绑定到全局环境了?

我自己加了最后两行代码,但是返回是false???然后我就懵了,是不是我对apply调用模式哪里理解错了?麻烦JS大神帮我解惑了[抱拳]


2018.5.22补充

首先这段代码是个简易的单例模式,即用一个变量来(ret)标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时(var script2=getScript();)
直接返回之前创建的对象(ret=document.createElement("script"))
所以第一个alert中script1和script2就是同一个对象,所以返回true。但是我自己加的script3相当于新建了一个与1、2不同的引用类型的变量,所以肯定是false了。

阅读 2.4k
1 个回答

你是对js的引用类型理解不充分

console.log(document.createElement("script")===document.createElement("script"))

你运行一下上面的代码,看看结果
还有

ret=fn.apply(this,arguments)

相当于

ret=document.createElement("script");

ret=(function(){
    return document.createElement("script");
}).apply(this,arguments)

ret=window.(function(arguments){
return document.createElement("script");
})=document.createElement("script");

是只有访问一个未定义的变量时,才会去window对象上面找

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏