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

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


当前回答

這是一個試圖清除一些(可能的)關於關閉的誤解,在其他答案中出現。

关闭不只是在您返回内部函数时创建。 事实上,关闭函数不需要完全返回,以便其关闭创建。 您可以将内部函数归咎于外部范围中的变量,或者将其作为一个论点转移到另一个函数,在那里它可以立即或随后被召回。

其他回答

想象一下,在你的城市里有一个非常大的公园,你会看到一个名叫Coder先生的魔法师在公园的不同角落开始棒球游戏,使用他的魔法窗口,称为JavaScript。

当然,每个棒球游戏都有相同的规则,每个游戏都有自己的分数板。

当然,一个棒球游戏的分数与其他游戏完全分开。

关闭是Coder先生保持所有他的魔法棒球游戏的分数的特殊方式。

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

    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

我写了一篇博客帖子一段时间后解释关闭,这里是我在关闭方面所说的,为什么你会想要一个。

关闭是让一个函数有持久的,私人变量的方式 - 也就是说,只有一个函数知道的变量,在那里它可以跟踪从以前运行的时间的信息。

在这个意义上,他们让一个函数有点像一个具有私人属性的对象。

完整帖子:

那么,这些关闭事物是什么呢?

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!");
};

要记住的事情

我很清楚地发现了JavaScript的第8章第6节“关闭”,《David Flanagan的最终指南》(The Definitive Guide),第6版,O’Reilly,2011年。

当一个函数被召唤时,创建了一个新的对象,以保持该召唤的本地变量,函数的范围取决于其声明位置,而不是其执行位置。

接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來,接下來。