JS中的闭包和上下文

在这里插入图片描述

变量提升 和 函数提升

这里要提到一个提升的概念,即在JS中,在解析代码之前还有一个预处理的过程,这个过程中会把部分变量和函数声明提前到代码的最顶部,
会在其他所有代码之前执行。虽然当我们按照规范(严格模式或者TS等良好的编码习惯)时并不会因为提升而发生意料之外的情况,不过作为原生
JS中的特性,我们还是需要了解一下。

函数提升

还记得在C语言中,我们往往会把函数签名的声明提前都放到文件的最前面,然后实现放在main函数后面吗?这就是因为函数要先声明后使用,而在
JS中,解析器已经帮我们做好了这件事情,所以我们在使用函数的时候不需要提前声明它,解析器会帮我们自动把函数声明提前到代码的最顶部。不过
需要说明的是这种提升只对声明后的函数有效(比如这种形式:function xxxx()),而对于函数表达式(let fun = function(){})则不会有提升效果。

变量提升

当我们使用var关键字声明变量的时候就会产生变量提升的效果,这带来的效果就是即使我们先使用某个变量然后再声明它也不会报错,
因为变量声明会被提前到代码的最顶部:

console.log(nameless);
var nameless = 'hello';

这样写是不会报错的,但是会打印出undefined,因为虽然声明提前来但是赋值并没有提前,所以在声明复制之前nameless的值就是undefined了。

这里还有一种情况,那就是我们同时声明了一个变量和一个函数,且他们的名称相同,这个时候只会提升他们的其中之一,并且函数的提升优先级是高于
变量的提升的
。不过现在我们应该遇不到这种情况了,因为这会在控制台中输出错误提醒我们。

建议

总而言之,建议我们还是使用ES6中的letconst关键字来声明变量和常量,因为这样可以避免变量提升带来的问题。最好的情况是直接使用
TypeScript,它提供的编译阶段检查可以帮助我们避免一些错误。

执行期上下文 和 this的指向

所谓执行期上下文,这个函数执行时的环境。在那些面向对象的编程语言中,我们可以把函数在哪里被定义的类的实例作为上下文来看,我觉得在
JS中也可以这样类比,不过不同的是JS中类的存在感比较低,常常一个函数被定义在一个object中,可以把他视作是一个匿名类的实例。

比如说我们有这么一个函数:

function anchor() {let count = 0;return {add: function () {console.log(`add anchor:${this.count++}`)},remove: function () {console.log(`remove anchor${this.count--}`)},printInfo: function () {console.log(`anchor count:${this}`)}}
}const anchorInstance = anchor();
anchorInstance.add();
anchorInstance.add();
anchorInstance.printInfo();

这个函数会返回一个对象,这个对象有三个方法,分别是增加this的count、减少this的count和打印this的指向。
当我们获得这个对象直接调用add或remove方法时:

add anchor:NaN
add anchor:NaN
anchor count:[object Object]

可以看到count的值是不正确的,我们更直观一点,直接打印count的值的话可以发现打印出来的是 undefined ,虽然我们在anchor函数中定义了count,
但是this.count并不会指向它,它指向的是所在对象的count,而所在对象中又没有定义count,所以就打印不出来了。当我们给这个对象加上count属性
后就可以正常打印了:

//调用
anchorInstance.count = 0;
anchorInstance.add();
anchorInstance.add();
anchorInstance.printInfo();
//结果:
// add anchor:0
// add anchor:1
// anchor count:[object Object]

这里我们再改动一下,把this关键字去掉结果发现也能正确打印信息。它正确使用到了anchor函数的局部变量,这实际上就产生了函数闭包。第二个原因就
是函数的作用域链,在嵌套的函数之中,变量会从内到外逐层寻找它的定义(就近原则),通过这种原则来决定取哪个值。当我们没有指定count的所在时,就会
根据作用域链向外寻找count变量。

除此之外,还需要注意的是关于箭头函数的this指向,匿名函数的this指向的是他的调用者,而箭头函数的this指向的是定义时寻找到的变量。这在
我们设置了原型的时候需要格外注意。

函数闭包

所谓闭包的意思就是函数内部的局部变量被外部持有了,类似于JVM中的可达性算法,由于这个变量被外部持有,也就是说正在被外部使用(不考虑内存泄漏)
那系统肯定不能把这个变量销毁,从而延长了函数局部变量的生命。

闭包在JavaScript中也有他的应用场景:

  • 数据封装和私有化
  • 作为函数工厂
  • 保留/追踪 函数的执行信息
  • 异步编程中(同步方式写异步)

上面的anchor函数中,我们使用的就是第一个应用场景,我们把count变量封装在了函数内部,外部只能通过return的接口来操作这个变量。

除此之外我觉得比较有用的就是追踪函数的执行信息了,比如我们可以封装这么一个函数:

let SecurityReporter = function() {let invokedInfos = [];return {connectDatabase() {const invokeInfo = {invokedTime : new Date(),invokedMethod : "[connect Database]"}invokedInfos.push(invokeInfo);},disconnectDatabase() {const invokeInfo = {invokedTime : new Date(),invokedMethod : "[disconnect Database]"}invokedInfos.push(invokeInfo);},reportInfos() {console.log(invokedInfos);}};
}const securityReporterIns = SecurityReporter();
securityReporterIns.connectDatabase();
securityReporterIns.disconnectDatabase();
securityReporterIns.reportInfos();

我们构建了一个类似于埋点上报的系统,当我们调用方法时就会自动把相关信息存储到一个闭包中,方便我们整理和排查日志。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/497377.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

17_HTML5 Web 存储 --[HTML5 API 学习之旅]

HTML5 Web 存储(Web Storage)是 HTML5 引入的一种在用户浏览器中存储数据的机制。它提供了比传统的 cookies 更加方便和强大的功能,包括更大的存储空间、更好的性能以及更简单的 API。Web 存储主要分为两种类型:localStorage 和 s…

如何在 Ubuntu 22.04 上使用 systemctl 管理 systemd 服务教程

简介 Systemd 是许多现代 Linux 发行版提供核心功能的默认服务管理器,而 systemctl 是用户与 systemd 服务交互的方式。这使得 systemctl 成为 Linux 管理员工具箱中重要的一部分。 在本文中,我们将探讨如何使用 systemctl 在使用 systemd 的系统上执行…

Unity3d UGUI如何优雅的实现Web框架(Vue/Rect)类似数据绑定功能(含源码)

前言 Unity3d的UGUI系统与Web前端开发中常见的数据绑定和属性绑定机制有所不同。UGUI是一个相对简单和基础的UI系统,并不内置像Web前端(例如 Vue.js或React中)那样的双向数据绑定或自动更新UI的机制。UGUI是一种比较传统的 UI 系统&#xff…

影刀进阶应用 | 知乎发布想法

文章目录 影刀进阶应用 | 知乎发布想法一、流程流程解释: 二、单条想法发布2.1 素材生产2.2 **进入发布流程**2.3 **输入文本**2.4 插入图片2.5 发布查看 三、批量发布 影刀进阶应用 | 知乎发布想法 一、流程 流程解释: 素材生产 :用AI生成待…

Win Server远程提示密码到期

背景 由于安全问题,取消了堡垒机直接托管资产的模式,需要用户通过堡垒机先登录操作机,然后通过操作机运维对应服务器 问题现象 调整运维模式后,发现原来堡垒机直接运维服务器时候,用户密码到期,可以要求…

GXUOJ-算法-第二次作业

1.矩阵连&#xff08;链&#xff09;乘 问题描述 GXUOJ | 矩阵连乘 代码解答 #include<bits/stdc.h> using namespace std;const int N50; int m[N][N]; int p[N]; int n;int main(){cin>>n;//m[i][j] 存储的是从第 i 个矩阵到第 j 个矩阵这一段矩阵链相乘的最小…

在线学习平台-项目技术点-前台

报错解决方法 1、P166-尚硅谷_在线教育_Nuxt整合错误_nuxt friendly-errors-CSDN博客 2、P168 3、P170 4、P173 npm remove axios npm install axios0.18.0 1、服务端渲染技术NUXT 1.1服务端渲染SSR 服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容&…

【探花交友】day03—MongoDB基础

目录 课程介绍 1、通用设置 1.1 需求分析 1.2 查询通用设置 1.2 陌生人问题 1.3 通知设置 1.4 黑名单管理 2、MongoDB简介 1.1、MongoDB简介 1.2、MongoDB的特点 1.3 数据类型 3、MongoDB入门 2.1、数据库以及表的操作 2.2、新增数据 2.3、更新数据 2.4、删除数…

基于Spring Boot + Vue3实现的在线商品竞拍管理系统源码+文档

前言 基于Spring Boot Vue3实现的在线商品竞拍管理系统是一种现代化的前后端分离架构的应用程序&#xff0c;它结合了Java后端框架Spring Boot和JavaScript前端框架Vue.js的最新版本&#xff08;Vue 3&#xff09;。该系统允许用户在线参与商品竞拍&#xff0c;并提供管理后台…

JVM学习-内存结构(二)

一、堆 1.定义 2.堆内存溢出问题 1.演示 -Xmx设置堆大小 3.堆内存的诊断 3.1介绍 1&#xff0c;2都是命令行工具&#xff08;可直接在ideal运行时&#xff0c;在底下打开终端&#xff0c;输入命令&#xff09; 1可以拿到Java进程的进程ID&#xff0c;2 jmap只能查询某一个时…

在线学习平台-项目技术点-后台

目录 1、主键生成策略 1.1自动增长-AUTO INCREMENT 1.2UUID 1.3Redis生成ID 2、MyBatis-plus 2.1自动填充 2.2悲观锁、乐观锁 2.3性能分析插件 3.ResponseBody和RequestBody 4.es6语法 4.1let变量和const变量 4.2解构赋值&#xff08;数组和对象解构 4.3模板字符串…

Redis 实战篇 ——《黑马点评》(上)

《引言》 在进行了前面关于 Redis 基础篇及其客户端的学习之后&#xff0c;开始着手进行实战篇的学习。因内容很多&#xff0c;所以将会分为【 上 中 下 】三篇记录学习的内容与在学习的过程中解决问题的方法。Redis 实战篇的内容我写的很详细&#xff0c;为了能写的更好也付出…

MySQL数据库——常见的几种锁分类

详细介绍MySQL的几种常见锁分类&#xff0c;如&#xff1a;表级锁、行级锁、页面锁、悲观锁、乐观锁、共享锁、排他锁、Gap-锁等。 文章目录 按锁粒度分表级锁行级锁页面锁锁与索引关系 按加锁机制分【逻辑上的锁】悲观锁乐观锁版本号机制CAS&#xff08;Compare and Swap&…

数据库sql语句单表查询

简单的增删改查操作 select count(*) from user where accountadmin and password123456 select count(*) from user where account"admin" insert into user(account,password) values ("admin","777") update user set password "666&…

OpenCV和PyQt的应用

1.创建一个 PyQt 应用程序&#xff0c;该应用程序能够&#xff1a; 使用 OpenCV 加载一张图像。在 PyQt 的窗口中显示这张图像。提供四个按钮&#xff08;QPushButton&#xff09;&#xff1a; 一个用于将图像转换为灰度图一个用于将图像恢复为原始彩色图一个用于将图像进行翻…

电路元件与电路基本定理

电流、电压和电功率 电流 1 定义&#xff1a; 带电质点的有序运动形成电流 。 单位时间内通过导体横截面的电量定义为电流强度&#xff0c; 简称电流&#xff0c;用符号 i 表示&#xff0c;其数学表达式为&#xff1a;&#xff08;i单位&#xff1a;安培&#xff08;A&#x…

win11中win加方向键失效的原因

1、可能是你把win键锁了&#xff1a; 解决办法&#xff1a;先按Fn键&#xff0c;再按win键 2、可能是可能是 贴靠窗口设置 中将贴靠窗口关闭了&#xff0c;只需要将其打开就好了

十二月第五周python

第一个程序&#xff0c;熟悉转换器&#xff0c;把加法计算器变成exe# // 1,制作加法计算器&#xff0c; # 输入两个数字得到相加结果并输出aint(input("输入数字&#xff1a;"))#int()是把输入的内容转换成整数&#xff0c; bint(input("输入数字&#xff1a;&…

pyqt和pycharm环境搭建

安装 python安装&#xff1a; https://www.python.org/downloads/release/python-3913/ python3.9.13 64位(记得勾选Path环境变量) pycharm安装&#xff1a; https://www.jetbrains.com/pycharm/download/?sectionwindows community免费版 换源&#xff1a; pip config se…

Lottie动画源码解析

Lottie是一个很成熟的开源动画框架&#xff0c;它支持直接使用从AE导出的动画文件&#xff0c;在不同平台均可快速使用&#xff0c;大大减轻了程序员的工作量&#xff0c;也让复杂的动画成为可能。该动画文件使用Json格式来描述内容&#xff0c;可以大大缩减文件的体积。在Andr…