JavaScript 核心概念 Closure

假设我们想设计一个计数器,每次调用方法 add(),计数器就加1。

如果使用局部变量,如下所示。实际上并不起作用,因为局部变量的作用域为函数本身。

function add() {
  var count = 0;
  count++;
}

add(); // 每次调用都是1
add(); // 每次调用都是1
add(); // 每次调用都是1

如果使用全局变量,如下所示。可以实现计数器功能,但是变量 count 也会被其他函数访问修改,并不安全。

var count = 0;
function add() {
  count++;
}

add();
add();
add();

console.log(count); // 3

JavaScript Closures

A closure is a function having access to the parent scope, even after the parent function has closed.
closure 是一个函数,该函数可以访问上一层的 Scope,即使 parent 函数已经结束。

在下面的代码中:

  • 变量 add 是一个 self-invoking 函数的返回值
  • 该 self-invoking 函数只执行一次,设置 count 为 0,返回一个函数表达式 function expression
  • 因此 add 实际上是一个函数,并且可以访问上一层 Scope 中的变量 count
  • 这就是所谓的 closure。它使得函数可以有一个 private 私有变量 count,该变量 count 只能通过 add() 方法访问。
var add = (function () {
    var count = 0;
    return function () { count++; return count; }
})(); // self-invoking 函数

console.log(add()); // 1
console.log(add()); // 2
console.log(add()); // 3

以上代码等同于如下代码:但是此处的 count 为全局变量,可能会被其他函数修改,不安全。

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

console.log(add()); // 1
console.log(add()); // 2
console.log(add()); // 3

一个常见面试题

for(var i = 1; i <= 5; i++) { // Global Scope i
    setTimeout(function() {
        console.log(i);
    }, i * 1000);
}

打印出 6 6 6 6 6

for(var i = 1; i <= 5; i++) {
    let j = i; // Block Scope j
    setTimeout(function() {
        console.log(j);
    }, i * 1000);
}

打印出 1 2 3 4 5


引用:
JavaScript Closures

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容