如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
当前回答
JavaScript 功能可以访问:
论点本地(即其本地变量和本地功能) 环境,其中包括:全球性,包括DOM在外部功能中的任何东西
请注意,外部功能不需要,尽管它们提供的好处我不在这里讨论。 通过访问其环境中的数据,一个关闭保持数据的生存. 在外部/内部功能的底部,外部功能可以创建本地数据,最终输出,但是,如果任何内部功能(s)在外部功能输出后生存,那么内部功能(s)保持外部功能的位置。
使用全球环境的封闭例子:
当用户点击 VoteUp 按钮时, voteUp_click 函数检查是否是VotedDown == 真实,以确定是否投票或仅仅取消投票。
var isVotedUp = false;
var isVotedDown = false;
function voteUp_click() {
if (isVotedUp)
return;
else if (isVotedDown)
SetDownVote(false);
else
SetUpVote(true);
}
function voteDown_click() {
if (isVotedDown)
return;
else if (isVotedUp)
SetUpVote(false);
else
SetDownVote(true);
}
function SetUpVote(status) {
isVotedUp = status;
// Do some CSS stuff to Vote-Up button
}
function SetDownVote(status) {
isVotedDown = status;
// Do some CSS stuff to Vote-Down button
}
其他回答
雖然在網路上有許多美麗的JavaScript關閉定義,但我試圖開始用我最喜歡的關閉定義來解釋我的六歲朋友,這幫助我更好地理解關閉。
关闭是一种内部功能,它可以访问外部(关闭)函数的变量 - 范围链. 关闭有三个范围链:它可以访问自己的范围(在其曲线手<unk>之间定义的变量),它可以访问外部函数的变量,并且可以访问全球变量。
关闭是指独立(自由)变量的函数,换句话说,关闭中定义的函数“记得”它所创造的环境。
关闭的用途:
关闭是有用的隐藏功能的实施,同时仍然揭示界面。
您可以使用关闭在 JavaScript 中模拟嵌入式概念。
關閉的例子:
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
function makeAdder(x) {
return {
add: function(y){
return x + y;
}
}
}
var add5 = makeAdder(5);
console.log(add5.add(2));//7
var add10 = makeAdder(10);
console.log(add10.add(2));//12
例子3:在jQuery中关闭
$(function(){
var name="Closure is easy";
$('div').click(function(){
$('p').text(name);
});
});
有用的链接:
感谢上面的链接,这有助于我更好地理解和解释关闭。
因为所有这些外部变量,由一个经文所指的函数,实际上是其经文所关闭的函数链中的本地变量(全球变量可以假设是某种根函数的本地变量),并且每个函数的单一执行都会产生其本地变量的新例子,因此,每个函数的执行都会返回(或以其他方式转换)。
此外,必须明白,JavaScript中的本地变量不是在滑板框中创建的,而是在滑板上,只有当没有人提到它们时才会被摧毁。当一个函数返回时,其本地变量的参考会减少,但如果在当前执行期间,它们成为关闭的一部分,并且仍然被其经文所定义的函数所提到。
一个例子:
function foo (initValue) {
//This variable is not destroyed when the foo function exits.
//It is 'captured' by the two nested functions returned below.
var value = initValue;
//Note that the two returned functions are created right now.
//If the foo function is called again, it will return
//new functions referencing a different 'value' variable.
return {
getValue: function () { return value; },
setValue: function (newValue) { value = newValue; }
}
}
function bar () {
//foo sets its local variable 'value' to 5 and returns an object with
//two functions still referencing that local variable
var obj = foo(5);
//Extracting functions just to show that no 'this' is involved here
var getValue = obj.getValue;
var setValue = obj.setValue;
alert(getValue()); //Displays 5
setValue(10);
alert(getValue()); //Displays 10
//At this point getValue and setValue functions are destroyed
//(in reality they are destroyed at the next iteration of the garbage collector).
//The local variable 'value' in the foo is no longer referenced by
//anything and is destroyed too.
}
bar();
关闭是一个代码块,符合三个标准:
它可以作为一个值进行转换,并在需要时由任何拥有这个值的人执行,当时它可以从它创建的背景中提到变量(即它关闭于变量访问,在“关闭”这个词的数学意义上)。
(“关闭”这个词实际上有一个不准确的含义,有些人不认为标准1是定义的一部分。
关闭是功能语言的支柱,但它们也存在于许多其他语言(例如,Java的匿名内部课堂)。你可以用它们做一些酷的事情:它们允许偏离的执行和一些优雅的风格技巧。
由: Paul Cantrell, @ http://innig.net/software/ruby/closures-in-ruby
最好的方法是不断地解释这些概念:
console.log(x);
// undefined
var x = 42;
console.log(x);
// 42
现在,JavaScript知道X是什么意思。
x = 43;
console.log(x);
// 43
现在,X意味着别的东西。
范围
当您创建一个函数时,该函数为变量具有自己的“盒子”。
function A() {
var x = 42;
}
console.log(x);
// undefined
var x = 42;
function A() {
console.log(x);
}
// 42
在函数 A 中,您有“范围访问”到 x。
function A() {
var x = 42;
}
function B() {
console.log(x);
}
// undefined
function A() {
var x = 42;
function B() {
console.log(x);
}
}
// 42
功能
在JavaScript中,您通过称之为:
function A() {
console.log(42);
}
A();
// 42
var a = function() {
console.log(42);
};
变量现在意味着一个功能,你可以运行它。
a();
// 42
setTimeout(a, 1000);
在一秒钟(1000毫秒),函数一个点被称为:
// 42
现在,当你定义函数时,这些函数可以访问它们的外部目标。
var a = function() {
var text = 'Hello!'
var b = function() {
console.log(text);
// inside function `b`, you have access to `text`
};
// but you want to run `b` later, rather than right away
setTimeout(b, 1000);
}
现在发生了什么?
// 'Hello!'
var c;
var a = function() {
var text = 'Hello!'
var b = function() {
console.log(text);
// inside function `b`, you have access to `text`
};
c = b;
}
// now we are out side of function `a`
// call `a` so the code inside `a` runs
a();
// now `c` has a value that is a function
// because what happened when `a` ran
// when you run `c`
c();
// 'Hello!'
您仍然可以在关闭范围内访问变量。
即使一个已经完成了运行,现在你正在运行C的外部。
在这里发生的事情被称为JavaScript中的“关闭”。
我思考关闭的越多,我会看到它作为一个2步过程: init - 行动
init: pass first what's needed...
action: in order to achieve something for later execution.
到6岁时,我会强调关闭的实际方面:
Daddy: Listen. Could you bring mum some milk (2).
Tom: No problem.
Daddy: Take a look at the map that Daddy has just made: mum is there and daddy is here.
Daddy: But get ready first. And bring the map with you (1), it may come in handy
Daddy: Then off you go (3). Ok?
Tom: A piece of cake!
例如:把一些牛奶带到妈妈(=行动)。首先做好准备,然后把地图(=init)带到这里。
function getReady(map) {
var cleverBoy = 'I examine the ' + map;
return function(what, who) {
return 'I bring ' + what + ' to ' + who + 'because + ' cleverBoy; //I can access the map
}
}
var offYouGo = getReady('daddy-map');
offYouGo('milk', 'mum');
因为如果你带着一个非常重要的信息(地图),你有足够的知识来执行其他类似的操作:
offYouGo('potatoes', 'great mum');
对于一个开发人员来说,我会在关闭和OOP之间进行平行。 init 阶段类似于在传统 OO 语言中向构建者传达论点; 行动阶段最终是你呼吁实现你想要的方法。
请参见我的另一个答案,描述OO和关闭之间的平行性:
如何在JavaScript中“正确”创建自定义对象?