如何向某人解释JavaScript关闭,知道它们所构成的概念(例如功能、变量等),但不了解关闭本身?

我已经在维基百科上看到了图表的例子,但不幸的是,它没有帮助。


当前回答

此答案的版本图像: [ 解决]

只是忘记每件事的范围,并记住:当一个变量需要在某个地方,JavaScript不会破坏它。

例子1:

此分類上一篇

例子2:

此分類上一篇

例子3:

其他回答

也许你应该考虑一个以对象为导向的结构而不是内部功能。

    var calculate = {
        number: 0,
        init: function (num) {
            this.number = num;
        },
        add: function (val) {
            this.number += val;
        },
        rem: function (val) {
            this.number -= val;
        }
    };

并从 calculate.number 变量中阅读结果,谁需要“返回”无论如何。

//Addition
First think about scope which defines what variable you have to access to (In Javascript);

//there are two kinds of scope
Global Scope which include variable declared outside function or curly brace

let globalVariable = "foo";

一件事要记住,一旦你宣布了一个全球变量,你可以在你的代码中的任何地方使用它,即使在功能中;

包含仅在您的代码的特定部分可用的变量的本地范围:

函数范围是当您在函数中宣布变量时,您只能在函数内访问变量。

function User(){
    let name = "foo";
    alert(name);
}
alert(name);//error

//Block scope is when you declare a variable within a block then you can  access that variable only within a block 
{
    let user = "foo";
    alert(user);
}
alert(user);
//Uncaught ReferenceError: user is not defined at.....

//A Closure

function User(fname){
    return function(lname){
        return fname + " " lname;
    }
}
let names = User("foo");
alert(names("bar"));

//When you create a function within a function you've created a closure, in our example above since the outer function is returned the inner function got access to outer function's scope

我思考关闭的越多,我会看到它作为一个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中“正确”创建自定义对象?

我倾向于通过好/坏的比较更好地学习,我喜欢看到工作代码跟随不工作的代码,有人可能会遇到,我把一个 jsFiddle 组合起来,它进行比较,并试图将差异推向我能找到的最简单的解释。

关闭是正确的:

console.log('CLOSURES DONE RIGHT');

var arr = [];

function createClosure(n) {
    return function () {
        return 'n = ' + n;
    }
}

for (var index = 0; index < 10; index++) {
    arr[index] = createClosure(index);
}

for (var index of arr) {
    console.log(arr[index]());
}

关闭错误:

console.log('CLOSURES DONE WRONG');

function createClosureArray() {
    var badArr = [];

    for (var index = 0; index < 10; index++) {
        badArr[index] = function () {
            return 'n = ' + index;
        };
    }
    return badArr;
}

var badArr = createClosureArray();

for (var index of badArr) {
    console.log(badArr[index]());
}

在上面的代码中,路径在创建ClosureArray()函数中移动,函数现在只会返回完成的路径,这在第一眼看起来更直观。

结果

第一個問題有一個引用:

如果你不能向六岁的人解释,你真的不明白。

这就是我会试图向一个真正的六岁男孩解释的方式:

你知道成年人如何拥有房子,他们称之为房子吗?当一个母亲有孩子时,孩子真的没有任何东西,对吗?但是她的父母拥有房子,所以每当有人问“你的房子在哪里?”孩子可以回答“那房子!”并指向父母的房子。

“关闭”是孩子能够永远(即使在国外)提到自己的家,即使是真正的父母拥有家。

关闭是一种功能,即使关闭了父母功能后,也可以访问父母范围。

var add = (function() {
  var counter = 0;
  return function() {
    return counter += 1;
  }
})();

add();
add();
add();
// The counter is now 3

例子解释:

变量添加被指定为自我召唤函数的回报值. 自我召唤函数只运行一次. 它将计算器设置为零(0),并返回函数表达式. 这种方式添加变成函数. “奇妙”部分是它可以在母范围内访问计算器. 这被称为JavaScript关闭。

来源