4

我有点困惑。

无论我在哪里,人们都说我应该使用自调用函数来确定范围,以避免全局命名空间污染。

但在这方面,自调用函数似乎与常规函数的行为相同,如下例所示:

function xx(){

    var x="variable";
    //logs into console
    console.log(x);
    }

xx();
//logs undefined
console.log(x);

所以,与常规函数和自调用的唯一真正区别是“自调用”部分,这意味着我不必在声明后手动运行函数?

4

4 回答 4

3

“自调用函数”是一个常见的 JavaScript 习惯用法的名称。它实际上不是一种函数。它是一个函数的立即执行。如果有帮助,您可以将其称为“立即调用的函数表达式”的 IIFE。

(function () { // Anonymous function expression
    // IIFE!
})(); // Invocation happens here with the ()!
var f = (function () { // Still anonymous
    // Almost immediately invoked function expression!
});

f(); // Invocation happens here!
var f = (function f() { // Not anonymous – now called “f”
    // Almost immediately invoked function expression!
});

f(); // Invocation happens here!
function f() { // Not anonymous
    // Almost immediately invoked function *declaration* – not an expression!
}

f(); // Invocation happens here!
于 2015-09-01T21:25:41.793 回答
2

自调用函数是普通函数,但没有名称。这使得它们只能在声明后立即调用,这实际上使它们成为一次性使用的函数,永远对其他代码隐藏。

正如你所指出的,表格

function foo() {
  console.log("foo");
}
foo()

(function () {
  console.log("foo");
})()

行为相同。

但是,第一种形式function foo() {...创建了一个命名函数,该函数存在于该范围内,直到该范围被销毁。对于全局范围,这永远不会发生,foo为您的应用程序中的任何其他代码留下一个有效且可调用的标识符。

这意味着任何时候,任何人都可以做

foo()

并再次初始化您的模块,或者可能获得模块新副本的句柄。

充其量,这可能会导致混乱和重复状态。在最坏的情况下,根据你的 IIFE 的结构,他们可能能够挖掘隐藏状态并开始以你意想不到的方式操纵它。

编写一个匿名且立即调用的函数可防止任何人再次调用它,从而使其成为创建和使用完全隐藏范围的干净且安全的方法。这就是为什么你经常看到它被用来提供私有状态或构建一个模块。

于 2015-09-01T21:21:52.213 回答
0

他们一定将 IIFE 与“自调用函数”混淆了。

这是本·阿尔曼(Ben Alman)写的:

“自执行匿名函数”有什么问题?</p>

您已经多次看到它提到过,但如果不清楚,我建议使用术语“立即调用函数表达式”,如果您喜欢首字母缩略词,则建议使用“IIFE”。向我建议了发音“iffy”,我喜欢它,所以让我们一起去吧。

什么是立即调用函数表达式?这是一个立即调用的函数表达式。就像名字会让你相信一样。

我希望看到 JavaScript 社区成员在他们的文章和演示文稿中采用术语“立即调用函数表达式”和“IIFE”,因为我觉得它使理解这个概念更容易一些,并且因为术语“自执行匿名函数”甚至都不准确:

  // This is a self-executing function. It's a function that executes (or
  // invokes) itself, recursively:

  function foo() { foo(); }

  // This is a self-executing anonymous function. Because it has no
  // identifier, it must use the  the `arguments.callee` property (which
  // specifies the currently executing function) to execute itself.

  var foo = function() { arguments.callee(); };

  // This *might* be a self-executing anonymous function, but only while the
  // `foo` identifier actually references it. If you were to change `foo` to
  // something else, you'd have a "used-to-self-execute" anonymous function.

  var foo = function() { foo(); };

  // Some people call this a "self-executing anonymous function" even though
  // it's not self-executing, because it doesn't invoke itself. It is
  // immediately invoked, however.

  (function(){ /* code */ }());

  // Adding an identifier to a function expression (thus creating a named
  // function expression) can be extremely helpful when debugging. Once named,
  // however, the function is no longer anonymous.

  (function foo(){ /* code */ }());

  // IIFEs can also be self-executing, although this is, perhaps, not the most
  // useful pattern.

  (function(){ arguments.callee(); }());
  (function foo(){ foo(); }());

  // One last thing to note: this will cause an error in BlackBerry 5, because
  // inside a named function expression, that name is undefined. Awesome, huh?

  (function foo(){ foo(); }());

资料来源:http ://benalman.com/news/2010/11/immediately-invoked-function-expression/

于 2015-09-01T21:44:48.867 回答
-1

// defined at `window`
function xx() {

  var x = "variable";
  //logs into console
  console.log(x);
}

xx();
// not defined at `window`
(function yy() {

  var y = "variable";
  //logs into console
  console.log("y:",y);
  // `window["yy"]` : `undefined`
  console.log("yy:", yy, "window['yy']:?", window["yy"]);
}());

console.log("xx", xx, window["xx"]);
try {
  console.log("yy:", yy, window["yy"]);
} catch (e) {
  console.log("yy:", e)
}
try {
  console.log("x:", x);
} catch (e) {
  console.log("x:", e)
}

于 2015-09-01T21:32:07.367 回答