如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?
我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。
当前回答
TLDR
细节
当一个函数通过内部(呼叫)方法引用时,函数对象的环境参考将复制到新创建的执行框架(stack frame)环境记录的外部环境参考。
在下面的例子中,函数f 关闭了全球执行背景的语法环境:
function f() {}
在下面的例子中,函数h在函数g的语法环境中关闭,而函数h则在全球执行背景的语法环境中关闭。
function g() {
function h() {}
}
如果内部函数由外部函数返回,则外部语法环境在外部函数返回后将继续存在,因为如果内部函数最终被召回,则外部语法环境必须可用。
其他回答
也许我们应该切断你的27岁的朋友,因为整个“关闭”的概念是(!)...... voodoo!
我意思的是:(a)你不直觉地期望它......(b)当有人花时间向你解释它时,你肯定不会期望它工作!
当你终于意识到这样的事情是可能的,那么......肯定......任何人的后事实反应会是:“whoa-a-a(!)...... kew-el-l-l...(!!!)”
直觉给了你很多完全可靠的期望,这样的事情会“当然,绝对是无意义的,因此是完全不可能的。
正如我所说的那样,“这就是伏地。
最好的方法是不断地解释这些概念:
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中的“关闭”。
让我们从这里开始,正如MDN所定义的那样:关闭是指独立(自由)变量的功能(被本地使用的变量,但在关闭范围内定义)。
function init() {
var name = 'Mozilla'; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
displayName();
}
init();
function init() {
var name = "Mozilla"; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert (name); // displayName() uses variable declared in the parent function
}
displayName();
}
init();
关闭现在考虑下面的例子:
function makeFunc() {
var name = 'Mozilla';
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
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
您可能想要做到这一点的情况在网上特别常见. 在前端JavaScript中写的代码的大部分是基于事件的 - 我们定义了一些行为,然后将其附加到用户发起的事件(如点击或键盘)。
例如,假设我们想添加一些按钮到一个页面,调整文本大小的一种方式是指定字体元素的字体大小在像素,然后设置页面上的其他元素的大小(如标题)使用相应的EM单位:
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
}
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.2em;
}
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}
var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}
var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
要了解更多关于关闭的信息,请访问MDN的链接
const makePlus = 函数(x) { 返回函数(y) { 返回 x + y; } const plus5 = makePlus(5); console.log(plus5(3));
如果JavaScript不知道关闭,会发生什么? 只需由其方法体(基本上是函数通话所做的事情)在最后一行中取代通话,你会得到:
console.log(x + 3);
现在, x 的定义在哪里? 我们没有在当前范围内定义它. 唯一的解决方案是让 plus5 携带其范围(或更好地说,其父母范围)。
TLDR
细节
当一个函数通过内部(呼叫)方法引用时,函数对象的环境参考将复制到新创建的执行框架(stack frame)环境记录的外部环境参考。
在下面的例子中,函数f 关闭了全球执行背景的语法环境:
function f() {}
在下面的例子中,函数h在函数g的语法环境中关闭,而函数h则在全球执行背景的语法环境中关闭。
function g() {
function h() {}
}
如果内部函数由外部函数返回,则外部语法环境在外部函数返回后将继续存在,因为如果内部函数最终被召回,则外部语法环境必须可用。