来自DailyJS "Let's build a JavaScript Framework"我对以下代码不太确定,显然是用作全局减排技术。
到目前为止,我对(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);
答案 0 :(得分:9)
(这个答案超过4年(截至2015年4月),虽然它仍然正确,但我认为需要更一般的解释 - 见下文)
想一想:
(function (x) {
// ...
})(y);
为:
function functionName(x) {
// ...
}
functionName(y);
但无需为其命名(如functionName)。
所以这个:
(function(global) {
// ...
})(typeof window === 'undefined' ? this : window);
真的只是:
function functionName(global) {
// ...
}
functionName(typeof window === 'undefined' ? this : window);
这是一个带有一个参数的函数(在函数中称为global
)并且使用typeof window === 'undefined' ? this : window
调用它,其含义与:
function functionName(global) {
// ...
}
if (typeof window === 'undefined') {
functionName(this);
} else {
functionName(window);
}
但使用较短的符号(并且没有命名函数)。
我在4年前写了这个答案,我认为是时候为这里涉及的概念添加一些更一般的解释了。
正如我上面解释的那样:
(function (x) {
// ...
})(y);
是这个的匿名版本:
function functionName(x) {
// ...
}
functionName(y);
(如果你只打电话一次)通常(参见下面的例外情况)也是如此:
function functionName() {
var x = y;
// ...
}
functionName();
回到匿名立即调用的函数,这个:
(function (x) {
// ...
})(y);
与此相同:
(function () {
var x = y;
// ...
})();
对大多数人来说可能有更明显的意义。 (这里立即调用的函数没有参数,仅用于为变量和其他嵌套函数提供一个独立的作用域,这样我们就不会污染外部或全局作用域 - 这也是使用参数的主要原因。立即调用匿名函数。)
顺便说一下,这个:
(function () {
// ...
})();
与此相同:
(function () {
// ...
}());
由于语言含糊不清,函数周围的括号是必需的,但它们可能包含实际调用函数的()
,或者它们可能没有 - 尽管有些人认为此处的第二种形式看起来更清晰。有关详细信息,请参阅this explanation by Douglas Crockford以及为什么他认为第一个版本看起来像“狗球”。
以前我说过这个:
(function (x) {
// ...
}(y));
与此相同:
(function () {
var x = y;
// ...
}());
这对于一个参数来说大部分时间都是正确的(它不会同时覆盖外部作用域中同名的变量,同时依赖于它的值),并且对于多个参数通常为true(如果他们也不依赖彼此。我希望这些例子会更清楚。
当我们有这个代码时:
(function (x) {
// ...
}(x + 1));
然后我们无法将其翻译成:
(function () {
var x = x + 1;
// ...
}());
因为在第一个版本中我们将外部 x
添加1并将结果绑定到内部 x
并且我们立即进入函数内部我们只有内部x
可以使用(甚至新的let
语句也无法帮助我们。)
另一个例子:
(function (x, outer_x) {
// ...
}(1, x));
在这里,您可以将old_x
的值从外部范围设置为x
,将内部范围中的x
设置为新值1,您不必担心关于订单。但如果你这样做了:
所以你看到有些情况你不能简单地翻译:
(function (x) {
// ...
}(y));
成:
(function () {
var x = y;
// ...
}());
但我认为,如果它可以翻译成第二种形式,那么它应该是为了可读性。特别是对于较大的功能,您不得不滚动到函数的末尾以了解函数顶部使用的变量是什么意思。
这意味着我会从问题中翻译此代码:
(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);
进入这个:
(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;
}
}());
我希望这个答案可以解释为什么这两个是等价的,甚至可以写成:
(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'});
它仍然意味着相同,同时可读性更低。
另见my other answer,其中我解释了类似的概念。
答案 1 :(得分:1)
这是一个匿名或lambda函数。大多数语言支持这一点
使用匿名函数实际上是作者的首选问题。如果不设置匿名函数来处理先前调用的返回值,则必须在客户端分配额外的内存,方法是初始化一个变量以包含返回的对象,然后将其传递给全局声明的函数。连续的方式。
如果它是1次功能,它可以节省空间,内存和时间。
作为旁注:你可以通过谷歌搜索函数式编程背后的一些概念来获得更好的感觉。 Lambda函数最近似乎风靡一时,特别是在Python中。