这种自调用匿名函数变体背后的原因
Posted
技术标签:
【中文标题】这种自调用匿名函数变体背后的原因【英文标题】:Reason behind this self invoking anonymous function variant 【发布时间】:2011-09-11 08:45:14 【问题描述】:在 github 上查看 code 时,我发现了以下内容:
(function()
).call(this);
这显然是一个自调用匿名函数。但是为什么会这样写呢?我习惯于看到规范变体(function() )()
。
将.call(this)
用于自调用匿名函数有什么特别的优势吗?
编辑:看起来一些 commonjs 环境将 this
设置为模块顶层的非全局值。哪些,以及他们将this
设置为您可能想要保留的内容?
【问题讨论】:
***.com/questions/36636/what-is-a-closure的可能重复 @Rob 我不认为这是 Sean 在这个问题中要问的问题。 啊,找到了——绝对不是重复的问题,但答案类似:***.com/questions/5211638/… 哦,很好的链接@Matt。我可以看到,如果函数是嵌套的,这很有意义。 ***.com/questions/4542942/… 对此答案的评论说,一些 commonjs 环境将this
设置为模块顶层的非全局变量。这可以解释为什么您可能需要保留 this
。
【参考方案1】:
默认情况下,调用(function()/*...*/)()
之类的函数会将函数中的this
的值设置为window
(在浏览器中),而不管this
的值可能在封闭上下文中,其中函数已创建。
使用call
允许您手动将this
的值设置为您想要的任何值。在这种情况下,它将其设置为 this
在封闭上下文中的任何值。
举个例子:
var obj =
foo:'bar'
;
(function()
alert( this.foo ); // "bar"
).call( obj );
http://jsfiddle.net/LWFAp/
您可以看到我们能够手动将this
的值设置为obj
变量引用的对象。
【讨论】:
他的问题是在末尾添加this
的作用,而不是添加自定义对象的作用。
@Startec:没有区别。他们会做同样的事情。他只是传递了一个不同的对象,因此他可以通过函数内部的this
显示该对象的属性可用。
@sixfingeredman 对,这表明您可以通过在右括号中传入一个对象来设置 this 的值。但是,问题是,当您传入this
对象时会发生什么,而不是您已实例化的某个对象。换句话说,如果传入this
只是在封闭函数this
中生成this
的值,那为什么还要传入呢?
@Startec:我明白你在说什么。由于它们实际上是相同的(除非在严格模式下),那有什么意义呢。虽然这个理由是基于 IIFE 的全球执行,但这个细节似乎稍后才添加到问题中。
有 ES2015 的方法吗?【参考方案2】:
.call(this)
(实际上只是()
,直到我改变它)确保您的***this
通过严格模式、--bare
选项和/或运行环境(***this
没有'不指向全局对象)。
【讨论】:
这些都没有任何意义。 啊——()
和 .call(this)
在严格模式下是不同的。现在一切都说得通了。 .call(this)
为函数提供相同的上下文是严格模式和宽松模式。
@matyr 您能否通过有关 () 和 .call(this) 的描述或链接进一步解释它们在严格模式下的实际含义?我无法理解严格模式位。
在宽松模式下,如果你调用一个没有对象的函数,this
被设置为window
。在严格模式下,this
设置为 undefined
。使用.call(this)
将this
(函数内部)显式设置为this
(函数外部),从而确保它保持为window
,无论您处于严格模式还是宽松模式。
谢谢,@SeanMcMillan。我其实明白你写的。我相信您的解释比答案要好得多。【参考方案3】:
通过使用:
> (function()
> ...
> ).call(this);`
然后将代码范围内的this(可能是全局对象)设置为函数的this对象。据我所知,它相当于:
(function(global)
// global references the object passed in as *this*
// probably the global object
)(this);
在浏览器中,window 通常是(或表现得好像是)全局对象的别名。
【讨论】:
第一个肯定不等于第二个。 它提供对外部执行上下文的 this 的引用,并将其存储为名为 global 的局部变量,而不是 this。所以它是等价的,它只是将引用分配给本地激活/变量对象的不同属性。【参考方案4】:C=
descript: "I'm C!<br>",
F: function()
//set this to the caller context's 'this'
(function()
document.write(this.descript);
).call(this);
//set this to 'window' or 'undefined' depend the mode
(function()
document.write(this.descript);
)();
//member function's 'this' is the object self
document.write(this.descript);
window.descript="I'm window!<br>";
C.F();
(function() ).call(this);
可以将匿名的this
设置为调用者上下文this
,上面是C
.(function() )();
将this
设置为window
或undefined
取决于模式。
【讨论】:
【参考方案5】:自调用函数对于在加载脚本时立即执行其内容很有用。这便于初始化全局范围元素。
【讨论】:
以上是关于这种自调用匿名函数变体背后的原因的主要内容,如果未能解决你的问题,请参考以下文章