当为函数创建一个局部变量时,每次调用该函数时,都会重新分配该数组,并将10个内容填充到其中。在更复杂的情况下,这可能需要时间。
这个闭包显然通过返回一个函数来解决这个问题。它返回的函数被赋值给digit name
,并立即调用该函数。我无法解开这个问题。现在我有点理解闭包是什么,但我不知道它是如何工作的。
var digit_names = (function() {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return names[n];
};
}());
alert(digit_names(3)); // 'three'
请详细说明这里发生了什么。如何在分配数组之前调用返回的函数?当我调用该函数时,如何在它到达返回函数之前忽略var names
?或者这个问题是否准确?
答案 0 :(得分:2)
闭包是捕获对本地数组names
的引用并将其保留在范围内。本地数组names
仅在调用外(匿名)函数时创建且完全,而不是在调用返回函数时。
每当调用返回的函数时,都会访问此相同的本地数组,因此不会重新创建数组。因此,这将具有类似的性能行为来缓存数组并重用它,而不是每次调用函数时重新分配它。
请注意,返回的函数不会在外部函数中调用 。它只在那里定义。
更新:OP似乎对名称digit_names
所指的功能感到困惑。名称digit_names
指的是外部函数返回的函数,不是外部函数本身。
从未给出名称的外部函数在调用时创建数组names
。外部函数然后生成内部函数,它捕获对names
的引用。外部函数然后返回内部函数,它将赋值给变量digit_names
。
因此,当在digit_names(3)
中调用内部(返回)函数时,它将直接访问由外部函数创建的数组成员,该函数从未具有名称。
请注意,当digit_names
被称为时,会创建无。所有创建都发生在产生digit_names
的匿名函数中。
答案 1 :(得分:1)
我首先回顾一下你的代码所做的事情,然后进一步解释是什么使它成为一个闭包。
var digit_names = (function() {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return names[n];
};
}());
alert(digit_names(3)); // 'three'
首先,您有一个立即调用的函数表达式(iife):
var digit_names = (function () {...}());
它的作用是定义一个函数,然后立即执行(或调用)它。在您的情况下,函数是:
function() {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return names[n];
};
}
这个函数的作用是首先定义一个包含数组的names
变量,然后返回一个匿名函数,该函数在执行时将从该数组返回一个元素。
现在让我们回到原始代码。
var digit_names = (function() {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
return function (n) {
return names[n];
};
}());
alert(digit_names(3)); // 'three'
digit_names
被定义为包含生命的返回值。这意味着,digit_names
包含此功能:
function (n) {
return names[n];
}
由于该函数是在iife中定义的,因此它可以访问iife中定义的所有变量,将names
定义为数组。函数引用names
数组的事实使它成为闭包。
digit_names
包含iife的返回值,它是一个从names数组中返回值的函数。通过引用names数组,该函数可以称为闭包。换句话说,digit_names
引用一个函数,该函数引用在定义函数的同一范围内定义的变量。
这是另一个例子:
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
var digit_names = function (n) {
return names[n];
}
alert(digit_names(3)); // 'three'
在这种情况下,digit_names
仍然存储对匿名函数的引用,而匿名函数仍然是一个闭包,但names数组不再是私有的。最终结果是相同的,因为names
只创建一次。
答案 2 :(得分:0)
在上面的示例中,您有一个立即调用的函数,它创建一次{{names}}数组,然后返回另一个引用该数组的函数。闭包关闭了 names数组,并确保只要存在对包含它的函数的引用,该数组就不会被垃圾收集。
您的示例在语义上等同于:
function closure() {
var names = ['zero', 'one', 'zero', 'one', 'zero', 'one', 'zero', 'one', 'zero', 'one'];
return function (n) {
return names[n];
};
}
var digit_names = closure();
{{closure}}仅被调用一次,并且返回的函数被分配给{{digit_names}}。 {{digit_names}}包含对{{closure}}的{{names}}变量的引用。
因为您只需创建一次{{names}},就可以节省分配时间。
答案 3 :(得分:0)
将封闭视为变形虫。它需要本地定义的变量,例如' names'并明确地关闭。然后它会引用'名称'数组无处可去,每次调用时都不会重新定义它。