如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
当前回答
关闭是一种功能,即使关闭了父母功能后,也可以访问父母范围。
var add = (function() {
var counter = 0;
return function() {
return counter += 1;
}
})();
add();
add();
add();
// The counter is now 3
例子解释:
变量添加被指定为自我召唤函数的回报值. 自我召唤函数只运行一次. 它将计算器设置为零(0),并返回函数表达式. 这种方式添加变成函数. “奇妙”部分是它可以在母范围内访问计算器. 这被称为JavaScript关闭。
来源
其他回答
关闭是一个代码块,符合三个标准:
它可以作为一个值进行转换,并在需要时由任何拥有这个值的人执行,当时它可以从它创建的背景中提到变量(即它关闭于变量访问,在“关闭”这个词的数学意义上)。
(“关闭”这个词实际上有一个不准确的含义,有些人不认为标准1是定义的一部分。
关闭是功能语言的支柱,但它们也存在于许多其他语言(例如,Java的匿名内部课堂)。你可以用它们做一些酷的事情:它们允许偏离的执行和一些优雅的风格技巧。
由: Paul Cantrell, @ http://innig.net/software/ruby/closures-in-ruby
(我没有考虑到6年前的事情。
在JavaScript等语言中,您可以将函数作为参数转移到其他函数(函数是第一级公民的语言),您往往会发现自己正在做这样的事情:
var name = 'Rafael';
var sayName = function() {
console.log(name);
};
你可以看到, sayName 没有定义的名称变量,但它使用的名称值被定义在 sayName 之外(在母范围内)。
functionThatTakesACallback(sayName);
请注意:
接下来会发生什么? 参考错误:未定义的名称?
因此: 即使名称不在函数 sayName 将被召唤的范围内(函数ThatTakesACallback 内), sayName 可以访问与 sayName 相关的关闭中捕获的名称值。
───
我喜欢Kyle Simpson的关闭定义:
关闭是函数能够记住和访问其语法范围,即使该函数在其语法范围之外运行。
语法范围是当一个内部范围能够访问其外部范围时。
此分類上一篇: You Don't Know JS: Scopes & Closures
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
function test() {
var bz = foo();
bz();
}
// prints 2. Here function bar referred by var bz is outside
// its lexical scope but it can still access it
test();
var foo = function() {
alert("Hello World!");
};
var bar = function(arg) {
return arg;
};
bar(foo)();
function add(value1, value2) {
function doAdd(operand1, operand2) {
return operand1 + operand2;
}
return doAdd(value1, value2);
}
var foo = add(1, 2);
// foo equals 3
function add(value1, value2) {
function doAdd() {
return value1 + value2;
}
return doAdd();
}
var foo = add(1, 2);
// foo equals 3
创建关闭 一个关闭是当一个内部函数从创建它的函数的外部可访问时创建的,这通常发生在一个外部函数返回一个内部函数时,当这种情况发生时,内部函数保持了一个参考到它创建的环境。
function add(value1) {
return function doAdd(value2) {
return value1 + value2;
};
}
var increment = add(1);
var foo = increment(2);
// foo equals 3
function increment(value2) {
return 1 + value2;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Closures</title>
<meta charset="UTF-8" />
<script>
window.addEventListener("load", function() {
window.setInterval(showMessage, 1000, "some message<br />");
});
function showMessage(message) {
document.getElementById("message").innerHTML += message;
}
</script>
</head>
<body>
<span id="message"></span>
</body>
</html>
window.addEventListener("load", function() {
var showMessage = getClosure("some message<br />");
window.setInterval(showMessage, 1000);
});
function getClosure(message) {
function showMessage() {
document.getElementById("message").innerHTML += message;
}
return showMessage;
}
模拟私人数据
function Person(name) {
this._name = name;
this.getName = function() {
return this._name;
};
}
var person = new Person("Colin");
person._name = "Tom";
// person.getName() now returns "Tom"
function Person(name) {
var _name = name;
this.getName = function() {
return _name;
};
}
var person = new Person("Colin");
person._name = "Tom";
// person._name is "Tom" but person.getName() returns "Colin"
在LOPS
<!DOCTYPE html>
<html lang="en">
<head>
<title>Closures</title>
<meta charset="UTF-8" />
<script>
window.addEventListener("load", function() {
for (var i = 1; i < 4; i++) {
var button = document.getElementById("button" + i);
button.addEventListener("click", function() {
alert("Clicked button " + i);
});
}
});
</script>
</head>
<body>
<input type="button" id="button1" value="One" />
<input type="button" id="button2" value="Two" />
<input type="button" id="button3" value="Three" />
</body>
</html>
要解决这个问题,关闭必须从实际路径变量中分开,这可以通过呼叫一个新的函数来完成,这反过来创造了一个新的参考环境,下面的例子表明如何做到这一点,路径变量转移到 getHandler() 函数, getHandler() 然后返回一个独立于原来的“为”路径的关闭。
function getHandler(i) {
return function handler() {
alert("Clicked button " + i);
};
}
window.addEventListener("load", function() {
for (var i = 1; i < 4; i++) {
var button = document.getElementById("button" + i);
button.addEventListener("click", getHandler(i));
}
});
function Person(name) {
var _name = name;
this.getName = function() {
return _name;
};
this.sayHello = function() {
alert("Hello!");
};
}
function Person(name) {
var _name = name;
this.getName = function() {
return _name;
};
}
Person.prototype.sayHello = function() {
alert("Hello!");
};
要记住的事情
没有自由变量的功能被称为纯功能。
包含一个或多个自由变量的功能被称为关闭。
var pure = function pure(x){
return x
// only own environment is used
}
var foo = "bar"
var closure = function closure(){
return foo
// foo is free variable from the outer environment
}
src: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure