帮助理解javascript全局减排技术

Ric*_*and 7 javascript globals

来自DailyJS "让我们构建一个JavaScript框架"我对以下代码不太确定,显然是用作全局减排技术.

到目前为止,我的理解是在(function(){}).我理解设置turing var up,将global.turing设置为turing,然后返回窗口或者这个(如果不是在浏览器中),但是(function(global){})(this或window)让我感到困惑......我见过像这样的东西

var mything = {} 并在我的东西下设置你的所有代码,但这个成语让我有点困惑.

我真的很想理解这里的推理并记住它"有效"

(function(global) {
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window);
Run Code Online (Sandbox Code Playgroud)

rsp*_*rsp 9

(这个答案超过4年(截至2015年4月),虽然它仍然正确,但我认为它需要更一般的解释 - 见下文)

原始答案

想一想:

(function (x) {
    // ...
})(y);
Run Code Online (Sandbox Code Playgroud)

如:

function functionName(x) {
    // ...
}
functionName(y);
Run Code Online (Sandbox Code Playgroud)

但无需为其命名(如functionName).

所以这:

(function(global) {
    // ...
})(typeof window === 'undefined' ? this : window);
Run Code Online (Sandbox Code Playgroud)

真的只是:

function functionName(global) {
    // ...
}
functionName(typeof window === 'undefined' ? this : window);
Run Code Online (Sandbox Code Playgroud)

它是一个带有一个参数global的函数(在函数内调用),它被调用,typeof window === 'undefined' ? this : window其含义与:

function functionName(global) {
    // ...
}
if (typeof window === 'undefined') {
    functionName(this);
} else {
    functionName(window);
}
Run Code Online (Sandbox Code Playgroud)

但使用较短的符号(并且没有命名函数).

更一般的解释

我在4年前写了这个答案,我认为是时候为这里涉及的概念添加一些更一般的解释了.

正如我上面解释的那样:

(function (x) {
    // ...
})(y);
Run Code Online (Sandbox Code Playgroud)

是这个的匿名版本:

function functionName(x) {
    // ...
}
functionName(y);
Run Code Online (Sandbox Code Playgroud)

哪个(如果你只调用一次)通常(见下面的例外情况)也与此相同:

function functionName() {
    var x = y;
    // ...
}
functionName();
Run Code Online (Sandbox Code Playgroud)

回到匿名立即调用函数,这个:

(function (x) {
    // ...
})(y);
Run Code Online (Sandbox Code Playgroud)

与此相同:

(function () {
    var x = y;
    // ...
})();
Run Code Online (Sandbox Code Playgroud)

这对大多数人来说可能有更明显的意义.(这里立即调用的函数没有参数,仅用于为变量和其他嵌套函数提供一个独立的作用域,这样我们就不会污染外部或全局作用域 - 这也是使用参数的主要原因.立即调用匿名函数.)

在括号上

顺便说一下,这个:

(function () {
    // ...
})();
Run Code Online (Sandbox Code Playgroud)

与此相同:

(function () {
    // ...
}());
Run Code Online (Sandbox Code Playgroud)

由于语言含糊不清,函数周围的括号是必需的,但它们可能包括()实际调用函数的函数,或者它们可能没有 - 尽管有些人认为这里的第二种形式看起来更清晰.有关详细信息,请参阅道格拉斯·克罗克福德的这一解释,以及为什么他认为第一个版本看起来像"狗球".

例外

以前我说过这个:

(function (x) {
    // ...
}(y));
Run Code Online (Sandbox Code Playgroud)

与此相同:

(function () {
    var x = y;
    // ...
}());
Run Code Online (Sandbox Code Playgroud)

这对于一个参数来说大部分时间都是正确的(在同一时间取决于它的值时,不会屏蔽外部范围中同名的变量),并且通常对于多个参数都是正确的(如果它们不是'也相互依赖).我希望这些例子会更清楚.

当我们有这个代码时:

(function (x) {
    // ...
}(x + 1));
Run Code Online (Sandbox Code Playgroud)

然后我们无法将其翻译成:

(function () {
    var x = x + 1;
    // ...
}());
Run Code Online (Sandbox Code Playgroud)

因为在第一个版本中我们将1添加到外部 x并将结果绑定到内部 x,一旦我们进入函数内部,我们只有内部x工作(甚至新let语句也无法帮助我们).

另一个例子:

(function (x, outer_x) {
    // ...
}(1, x));
Run Code Online (Sandbox Code Playgroud)

在这里,您可以设置old_x的值设置为x从外范围,x在范围内为1的新值,您不必担心秩序.但如果你这样做了:

摘要

所以你看到有些情况你不能简单地翻译:

(function (x) {
    // ...
}(y));
Run Code Online (Sandbox Code Playgroud)

成:

(function () {
    var x = y;
    // ...
}());
Run Code Online (Sandbox Code Playgroud)

但我认为,如果它可以翻译成第二种形式,那么它应该是为了可读性.特别是对于较大的功能,你不得不滚动到函数的末尾以了解函数顶部使用的变量是什么意思.

回到问题

这意味着我会从问题中翻译此代码:

(function(global) {
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window);
Run Code Online (Sandbox Code Playgroud)

进入这个:

(function () {
  var global = typeof window === 'undefined' ? this : window;
  var turing = {
    VERSION: '0.0.1',
    lesson: 'Part 1: Library Architecture'
  };

  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
}());
Run Code Online (Sandbox Code Playgroud)

我希望这个答案可以解释为什么这两个是等价的,它甚至可以写成:

(function (global, turing) {
  if (global.turing) {
    throw new Error('turing has already been defined');
  } else {
    global.turing = turing;
  }
})(typeof window === 'undefined' ? this : window,
   {VERSION: '0.0.1', lesson: 'Part 1: Library Architecture'});
Run Code Online (Sandbox Code Playgroud)

它仍然意味着相同,同时可读性更低.

另见我的其他答案,我解释了类似的概念.