JavaScript自执行函数-有什么区别?

7

我非常熟悉自执行函数,因为我曾在使用jQuery时接触到它们。

(function($) { /* do stuff */ })(jQuery);

今天我在阅读backbone.js源代码时注意到他们这样做:
(function() { /* do stuff */ }).call(this);

这是否达到了相同的效果?以下两行代码是否会做同样的事情?
(function($) { /* do stuff */ })(jQuery);
(function($) { /* do stuff */ }).call(jQuery);
4个回答

12

第一种形式是传递一个参数,而第二种形式是在执行函数内设置'this'所引用的内容。它们是不同的。

(function(x){ console.log(this,x); })( jQuery );
//--> [window object]
//--> [jQuery object]

(function(x){ console.log(this,x); }).call( jQuery );
//--> [jQuery object]
//--> undefined

(function(x){ console.log(this,x); }).call( jQuery, jQuery );
//--> [jQuery object]
//--> [jQuery object]

若想了解更多信息,请参见Function.prototype.callFunction.prototype.apply

下面是一个使用call技术的案例:

v = 'oh noes!'
var o = {
  v : 42,
  f : function(){
    console.log(this.v);
    (function(){ console.log(this.v) })();
  }
};
o.f();
// --> 42
// --> 'oh noes!'

如果没有通过call()设置this的值,那么自调用函数会在全局作用域(window)中被调用,而不是当前对象的作用域。


1
虽然如果它是call(jQuery, jQuery),它会同时设置两个。 - zzzzBov
@Phrogz 在调用(jQuery, jQuery)函数中,是将第二个参数传递给函数吗? - Danny
@Danny 正确;欲了解更多详细信息,请查看 Function.prototype.call 的文档。 - Phrogz
@Danny:是的。call 的第一个参数是要用于 this 的值;随后的参数将传递给函数。(详见我的回答。) - T.J. Crowder

3
他们的情况如下:
(function() { /* do stuff */ }).call(this);

...他们确保使用特定值调用函数中的this(例如,函数内部的this将与函数外部的this相同)。

在你的情况下:

(function($) { /* do stuff */ })(jQuery);

...this在你的函数内部将是全局对象,因为你调用它时没有设置任何东西,所以this默认为全局对象(在浏览器上是window)。

在JavaScript中,this完全由函数的调用方式决定。有两种主要方式:

  1. By calling the function as part of the expression that retrieves it from an object property, e.g.

    obj.foo(); // Or `obj["foo"]();
    

    In that case, within the call to foo, this will refer to obj.

  2. By calling the function via its built-in call or apply methods:

    var obj = {name: "Fred"};
    function foo(salutation, punctuation) {
        alert(salutation + " " + this.name + punctuation);
    }
    foo.call(obj, "Hi", "!");    // alerts "Hi Fred!"
    foo.apply(obj, ["Hi", "!"]); // Also alerts "Hi Fred!"
    

    The only difference between call and apply is how you specify arguments to pass into the function you're calling: With call, you just list them as discrete arguments following the this value you want; with apply, you supply them as an array.


1

第一个将jQuery作为参数$传递。第二个使jQuery成为函数内的'this'变量。


-2

.call 将函数放在闭包作用域中。

所以如果你这样做:

(function($) { /* do stuff */ }).call(jQuery);

$ 会变成 未定义


1
-1 对于混淆/不正确的术语;call与闭包无关。 - Phrogz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接