如何理解JavaScript的闭包

闭包是JavaScript一个重要的感念,但到底什么是闭包,很多人却说不太清楚。关于闭包有两个大家都比较认同的定义:

定义1

A closure is a function that has access to the parent scope, even after the scope has closed.

定义2

A closure is the combination of a function and the lexical environment within which that function was declared.

要想理解闭包,就先要理解Scope(作用域)的概念。作用域就是一个JavaScript变量在何时何地可以被其他函数使用。

当你创建了一个JavaScript函数(function)时,这个函数是可以访问它被创建时内部和外部的变量。举一个栗子:

function sayHi() {
  var who = 'Chris';
  console.log(who);
}
sayHi(); // 'Chris'
console.log(who); // Uncaught ReferenceError: who is not defined

栗子中的 who 就是函数内部变量,即函数内部作用域的变量。变量 who 不能被全局作用域的代码访问,因为它在 sayHi 这个函数的内部作用域内。但如果将代码修改成:

var who = 'Chris';
function sayHi() {
  console.log(who);
}
sayHi(); // 'Chris'
console.log(who); // 'Chris'

who 在全局作用域中,对于 sayHi 来说它是自己的外部作用域中的变量,所以可以被访问到。

再举一个函数嵌套函数的栗子:

function toWho() {
  return function sayHi() {
    var who = 'Chris';
    console.log(who);
  }
}
var greeting = toWho();
greeting(); // 'Chris'

这段代码中,调用 toWho 后返回的是一个函数,在返回的这个函数被调用时,它(sayHi)可以访问自己内部定义的变量(who)。如果我们挪动一行代码,看看会有什么变化。

function toWho() {
  var who = 'Chris';
  return function sayHi() {
    console.log(who);
  }
}
var greeting = toWho();
greeting(); // 'Chris'

可以看到,控制台上会打出 who 这个变量的值(Chris)。当toWho函数被调用后,它的函数体已经执行结束,闭包也已经关闭,返回了一个新函数给变量 greeting 。当 greeting 被调用时,执行的是 sayHi 的函数体。尽管在函数 sayHi 中没有定义 who 变量,但当 greeting 被调用的时候还是可以访问到 sayHi 的父作用域的变量。到此,我们刚刚使用了一个闭包

闭包就是一个函数在它的作用域关闭后,还可以访问它父作用域的变量。

内部函数 sayHi 创建了一个闭包,来维护它父作用域 toWho 函数中的变量。所以当被 greeting 调用时,who 这个变量可以被访问到。

每一个JavaScript函数都会有一个闭包,你不需要做额外的工作来显性的声明闭包。

再来看一个闭包的栗子:

function sayHi(a) {
  return function(b) {
    return `${a} say hi to ${b}`;
  };
}

var x = sayHi('Chris');
var y = sayHi('Kitty');

x('David');  // 'Chris say hi to David'
y('Will');  // 'Kitty say hi to Will'

变量 a 在匿名函数的闭包中,所以当 xy 函数被调用时,a 是可以被访问到的。

转载于:https://my.oschina.net/u/3365822/blog/1504002

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值