3.闭包 - JS

news/2024/7/19 13:52:17 标签: javascript, 前端, 开发语言, js, ecmascript, 笔记, 学习

作用域

一般认为 JS 中作用域有三种:

  • 全局作用域:一个脚本运行代码的默认作用域;
  • 模块作用域:一个模块运行代码的默认作用域;
  • 函数作用域:一个函数运行代码的默认作用域。

而由于 let/const 声明变量的作用域,是比函数作用域更加具有块级属性的,所以称块级作用域,任何一个 {} 包围的代码都是一个;函数是特殊的块,脚本是一个大的块,模块是多个脚本的集合,是更大的块。

函数是特殊的块?这是由于,函数体内就算是 var 声明的变量,在外部也无法使用,这和其他 {} 构成的块不同。换句话说,var 只承认函数的块级作用域。

js">/* let/const 声明变量的作用域 */
{ let a = 1; }
console.log(a)		// 报错,块内的变量在外部失效,报未定义的错

{ let a = 1 }
{ console.log(a) }	// 报错,此块内没有变量a

for (let i = 0; i < 5; i++) {  }
console.log(i)		// 报错,块内的变量在外部失效,报未定义的错

for (var i = 0; i < 5; i++) {  }
console.log(i)		// 5 var 只承认函数的块级作用域

闭包

闭包是 JS 中最强大的特性之一。尽管功能强大,但除了完成特定任务时,才会函数嵌套。

概念

JS 允许函数嵌套,且根据 块/函数 的作用域特性(内部可以访问外部声明定义的变量),将外部函数声明的变量等组成的环境一个内部函数组合封装起来,就构成一个闭包

在下面一个简单的计数器例子中,内部函数 counter 和变量 n/init 组成的环境,构成闭包。

js">function MakeCounter(init=0) {
	let val = init;
	function counter() { return val++; }
	return counter
}

let ctr = MakeCounter(10)
ctr()		// 10
ctr()		// 11
ctr()		// 12

模拟私有方法

由于闭包环境变量的私有性,容易想到用来模拟一些私有方法。

下面一个相对复杂的计数器例子中:私有属性 privateVal 只能通过公共方法 getValue 进行访问;私有方法 changeBy 也只能通过其他公共方法调用。

js">function MakeCounter(init) {
	let privateVal = init;
	function changeBy(delta) { privateVal += delta; };
	return {
		getValue() { return privateVal; },
		increment() { changeBy(1); },
		decrement() { changeBy(-1); },
		plus(b) { changeBy(b); },
		minus(b) { changeBy(-b); },
	}
}

let ctr = MakeCounter(10);
ctr.value()				// 10
ctr.increment()
ctr.plus(9)
ctr.value()				// 20

多个闭包共用一个环境?

将上面计数器的例子小改一下,在返回的对象里增加一个值。

返回时一个对象,包括一个值和五个函数:

  • 五个函数共用一个环境,影响同一个环境;
  • val,在完成返回后,脱离该环境,独立成为一个变量/属性。
js">function MakeCounter(init) {
	let privateVal = init;
	function changeBy(delta) { privateVal += delta; };
	return {
		val: PrivateVal,
		getValue() { return privateVal; },
		increment() { changeBy(1); },
		decrement() { changeBy(-1); },
		plus(b) { changeBy(b); },
		minus(b) { changeBy(-b); },
	}
}

let ctr = MakeCounter(10);
ctr.getValue()			// 10
ctr.val					// 10
ctr.increment()
ctr.plus(9)
ctr.getValue()			// 20
ctr.val					// 10
ctr.val = 100
ctr.val					// 100

性能考量

  1. 闭包在处理速度和内存消耗方面对脚本性能具有负面影响;
  2. 闭包特性能达到的效果,使用高级语法也能实现;
  3. 高手总是会闭包。

http://www.niftyadmin.cn/n/5359586.html

相关文章

HiveSQL题——array_contains函数

目录 一、原创文章被引用次数 0 问题描述 1 数据准备 2 数据分析 ​编辑 3 小结 二、学生退费人数 0 问题描述 1 数据准备 2 数据分析 3 小结 一、原创文章被引用次数 0 问题描述 求原创文章被引用的次数&#xff0c;注意本题不能用关联的形式求解。 1 数据准备 i…

易点易动设备管理平台助力制造企业实现设备智能化管理

在当今高度竞争的制造业市场中&#xff0c;制造企业面临着日益复杂的设备管理挑战。为了提升生产效率、降低成本并保证产品质量&#xff0c;制造企业迫切需要一种智能化的设备管理解决方案。易点易动设备管理平台应运而生&#xff0c;它为制造企业提供了全面的设备管理功能&…

如何在Shopee平台上进行手机类目选品?

在Shopee平台上进行手机类目的选品是一个关键而复杂的任务。卖家需要经过一系列的策略和步骤&#xff0c;以确保选品的成功和销售业绩的提升。下面将介绍一些有效的策略&#xff0c;帮助卖家在Shopee平台上进行手机类目选品。 先给大家推荐一款shopee知虾数据运营工具知虾免费…

UbuntuServer22.04LTS在线安装MySQL8.x

UbuntuServer22.04LTS在线安装MySQL8.x 文章目录 UbuntuServer22.04LTS在线安装MySQL8.x1. 安装1. 官网2. 在线安装3. 修改密码及设置远程登录4. 其他配置参考 2. 启动和停止1. 查看运行状态2. 开机自启3. 查看默认服务器配置命令 3. 登录 1. 安装 1. 官网 官网安装文档&#…

【使用python压缩pdf文件大小】

工作中常需要压缩数据文件大小&#xff0c;压缩PDF文件是一种减少PDF文件大小的方法&#xff0c;这样可以使文件更易于传输和存储。下面是一些常见的压缩PDF文件的方法&#xff1a; A. 常见的压缩PDF文件的方法 在线压缩工具&#xff1a;有很多在线的PDF压缩工具&#xff0c;…

Java List的合并与切分

在Java开发中经常遇到list结构数据的处理&#xff0c;如List的合并或拆分&#xff0c;记录下来&#xff0c;方便备查。 一、List 合并 两个list数据的合并处理&#xff0c;可使用Java8 新特性的stream流&#xff0c;根据实际需要遍历取值。 1、定义 UserInfo 对象 订单的相…

极简网络邻区自动化操作流程指导手册

一、创建任务 1、策略配置&#xff1a;首先按配置内容进行个性化策略配置 2、任务创建&#xff1a;在专题分析->极简网络分析->极简网络配置任务管理下点击创建任务&#xff0c;具体内容如下填写&#xff1a; 目前策略配置一般配置为城区场景和农村场景&#xff0c;各地…

【Qt基本功修炼】Qt线程的两种运行模式

1. 前言 QThread是Qt中的线程类&#xff0c;用于实现多线程运行。 QThread有两种工作模式&#xff0c;即 消息循环模式无消息循环模式 两种模式分别适用于不同的场景。下面我们将从多个方面&#xff0c;讲解QThread两种工作模式的区别。 2. 消息循环模式 2.1 实现原理 Q…