ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

个人对 JavaScript 闭包的理解

2022-08-30 01:31:25  阅读:290  来源: 互联网

标签:闭包 函数 作用域 JavaScript add 理解 del let


作用域的概念

同级作用域

在一个作用域中声明相同名称的变量会发生变量名冲突的问题。假如在作用域 A 中声明一个变量 a,作用域 B 也声明一个变量 a,两个作用域的变量都互不影响。

// 作用域 A
{
  let a = 0;
  console.log(a);
}

// 作用域 B
{
  let a = 10;
  console.log(a);
}

第一个打印 0,第二个打印 10。

嵌套作用域

作用域是可以嵌套的,作用域 A 嵌套作用域 B,此时两个作用域分别声明变量 a,也是不冲突的。

{// 作用域 A
  let a = 0;
  console.log(a);
  { // 作用域 B
    let a = 10;
    console.log(a);
  }
}

第一个打印 0,第二个打印 10。

在嵌套作用域中,子作用域 B 可以访问父作用域 A 的变量,也可以影响它的父作用域 A。

{
  let a = 0;
  {
    a = 10;
    console.log(a);
  }
}

最终打印的结果是 10。

函数的闭包

JS 的类实际上就是在使用函数的闭包。每执行一次函数就是在生成一个新的作用域,这些新的作用域就像是上面提到的,它们互不影响,只有它们的子作用域可以影响父作用域,即闭包。

闭包缓存数据

function Counter(x) {
  return {
    add: y => {
      return (x = x + y);
    },
    del: y => {
      return (x = x - y);
    }
  };
}

add 和 del 都是父函数 Counter 的子函数,它们之间是一个闭包关系。创建两个 Counter 的实例:

let c1 = Counter(10);
console.log(c1.add(20));
console.log(c1.del(40));

当执行c1.add()时,左边有一个 Closure,说明已经形成了一个闭包:

Closure 中只有 x 是受闭包影响被缓存下来的数据,也就是父函数 Counter 的变量。Local 代表 add 函数自身的变量,没有与其他函数之间(或作用域)形成关系,也就不符合闭包的存在条件,只能由 add 函数自己来使用。

再继续往下执行,可以看到此时 Closure 中的 x 已经是 30:

再往下执行,调用 del 函数,再执行函数的相减操作之间,我们可以看到 Closure 中的 x 还是上一次的结果:30。

再接着往下执行一次,del 函数相减之后,Closure 中的 x 的结果是 -10:

本节小结

受闭包的影响,父函数的数据被缓存下来,子函数可以自由地使用,而且再内存中也不会被销毁。

闭包的好处

仔细观察上面的例子,add 和 del 函数都依赖了相同的变量 x,而这个 x 是父函数给的,再闭包中被缓存起来。add 和 del 只需要传递新的参数就可以参与运算,也就是说,闭包可以减少我们函数的参数传递,使得我们一个计算操作更加连贯,且降低代码耦合度。

假如不使用闭包,通过函数的参数传递来计算,替代上面的闭包函数:

function add(x, y) {
  return (x = x + y);
}

function del(x, y) {
  return (x = x - y);
}

let res = add(10, 20);
let ser = del(res, 40);

就很没有必要,何不如把 x 抽离出来呢?变成一个全局变量:

let x = 10;

function add(y) {
  return (x = x + y);
}

function del(y) {
  return (x = x - y);
}

let res = add(20);
let ser = del(40);

可以,但是不推荐,全局作用域中,变量 x 被声明一次,假如代码越写越多,变量是不是会冲突,代码是不是变得难以维护?闭包可以把 add 和 del 以及 x 都囊括在一个作用域里,也不影响其他的作用域。

本节小节

闭包可以把一块代码容纳在一个里面,形成一个整体,一个不受其他作用域影响的作用域。是不是很像模块开发?没错,我猜测 CommonJS 就是使用的闭包。

总结

  1. 闭包可以让我们使用模块开发思想来写代码,把一系列代码揉进闭包里,是一个有机的结合。类就是使用的闭包,在早期通过闭包来实现模块的开发。

  2. 闭包可以缓存父函数的变量,子函数可以使用,子函数修改父函数的变量,其他子函数也跟着改变。

标签:闭包,函数,作用域,JavaScript,add,理解,del,let
来源: https://www.cnblogs.com/Enziandom/p/16637916.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有