如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
当前回答
维基百科 关闭:
在计算机科学中,关闭是一种函数,以及该函数的非本地名称(自由变量)的参考环境。
技术上,在JavaScript中,每个功能都是一个关闭,它总是有在周围范围内定义的变量访问。
由于JavaScript的范围定义结构是一种功能,而不是像许多其他语言一样的代码区块,我们通常在JavaScript中关闭的意思是与已执行的周围功能中定义的非本地变量的功能。
密封经常用来创建一些隐藏的私人数据的功能(但这并不总是如此)。
var db = (function() {
// Create a hidden object, which will hold the data
// it's inaccessible from the outside.
var data = {};
// Make a function, which will provide some access to the data.
return function(key, val) {
if (val === undefined) { return data[key] } // Get
else { return data[key] = val } // Set
}
// We are calling the anonymous surrounding function,
// returning the above inner function, which is a closure.
})();
db('x') // -> undefined
db('x', 1) // Set x to 1
db('x') // -> 1
// It's impossible to access the data object itself.
// We are able to get or set individual it.
EMS
上面的例子是使用一个匿名函数,一次执行,但它不一定是. 它可以被命名(例如 mkdb)并后续执行,每次被召唤时产生一个数据库函数. 每一个所产生的函数都会有自己的隐藏的数据库对象. 另一个使用例子关闭是当我们不返回一个函数时,但包含多个函数的对象
其他回答
第一点的例子 由 dlaliberte:
关闭不只是在您返回内部函数时创建。 事实上,关闭函数根本不需要返回. 您可以将内部函数归咎于外部范围中的变量,或者将其作为一个论点转移到另一个函数,在那里它可以立即使用。
var i;
function foo(x) {
var tmp = 3;
i = function (y) {
console.log(x + y + (++tmp));
}
}
foo(2);
i(3);
关闭是函数被关闭时,函数被定义为名称空间,函数被召唤时是不可变的。
在JavaScript中,它发生时:
定义一个函数在另一个函数内 内部函数在外部函数返回后被召回
// 'name' is resolved in the namespace created for one invocation of bindMessage
// the processor cannot enter this namespace by the time displayMessage is called
function bindMessage(name, div) {
function displayMessage() {
alert('This is ' + name);
}
$(div).click(displayMessage);
}
我认为值得回头迈出一步,并考虑一个更普遍的“关闭”概念 - 所谓的“加入运营商”。
在数学中,“加入”操作员是部分命令集中的一个函数,返回最小的对象,大于或等于其论点。在符号中,加入 [a,b] = d 如 d >= a 和 d >= b,但没有一个 e 如 d > e >= a 或 d > e >= b。
因此,加入给你最小的东西“大”比部分。
现在,请注意,JavaScript Scopes 是一个部分安排的结构,所以有一个敏感的概念加入,特别是,一个加入 Scopes 的最小范围比原始 Scopes 大。
因此,对变量A、B、C的关闭是最小的范围(在您的程序的细节中!)将A、B、C带入范围。
查找描述的解释:如何在场景背后的JavaScript关闭工作。
文章解释了范围对象(或LexicalEnvironments)如何分配并以直观的方式使用。
"use strict";
var foo = 1;
var bar = 2;
function myFunc() {
//-- Define local-to-function variables
var a = 1;
var b = 2;
var foo = 3;
}
//-- And then, call it:
myFunc();
在执行顶级代码时,我们有以下范围对象的安排:
此分類上一篇
当 myFunc() 被召唤时,我们有以下范围链:
此分類上一篇
了解范围对象是如何创建,使用和删除,这是一个关键,有一个大图像,并了解如何在盖子下工作关闭。
请参见上述文章,详细信息。
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!");
};
要记住的事情