深入理解JS的执行上下文、词法作用域和闭包(下)

news2024/11/23 8:28:53

在这里插入图片描述

🤍 前端开发工程师、技术日更博主、已过CET6
🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1
🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》
🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》

文章目录

  • 四、总结 🎯
    • 执行上下文、词法作用域和闭包的关系
    • 理解这些概念对编程的重要性 💪
    • 实际应用中的注意事项和最佳实践 👀
  • 参考资料

四、总结 🎯

执行上下文、词法作用域和闭包的关系

在JavaScript中,执行上下文、词法作用域和闭包之间存在一些复杂的关系。下面详细解释这些关系:

执行上下文:

执行上下文是JavaScript中变量、函数和对象等执行时的上下文环境。JavaScript中,执行上下文主要包括全局执行上下文(Global Execution Context)和函数执行上下文(Functional Execution Context)。

全局执行上下文包含全局作用域中的变量、函数和对象等。函数执行上下文则包含函数词法作用域中的变量、函数和对象等。

当执行一段代码时,首先会创建全局执行上下文,将全局变量、函数和对象等放入其中。然后,按照代码中的函数调用顺序,依次创建函数执行上下文,并将函数词法作用域中的变量、函数和对象等放入其中。

词法作用域:

词法作用域是由代码文本中变量声明的位置决定的。在JavaScript中,词法作用域主要包括函数词法作用域和块级作用域。

函数词法作用域是指函数可以访问其词法作用域中的变量,即使这个函数在其词法作用域之外执行。块级作用域是指使用letconst声明的变量具有块级作用域,只能在声明它们的代码块(如for循环、if语句等)内部访问。

词法作用域主要影响变量的查找和函数的调用。当需要在某个作用域中查找变量或调用函数时,JavaScript会按照词法作用域的规则,从当前作用域开始,向上级作用域逐层查找,直到找到为止。

闭包:

闭包(Closure)是JavaScript中一种重要的概念,它指的是一个函数可以访问其词法作用域中的变量,即使这个函数在其词法作用域之外执行。

闭包的主要特点包括函数可以记住并访问其词法作用域,即使这个作用域在函数执行完毕后被销毁。当一个函数在其词法作用域之外执行时,即使这个作用域在函数执行完毕后被销毁,该函数仍然可以访问其词法作用域中的变量。

总之,执行上下文、词法作用域和闭包之间的关系主要体现在以下几个方面:

  • 执行上下文是JavaScript中变量、函数和对象等执行时的上下文环境,词法作用域主要影响变量的查找和函数的调用。
  • 词法作用域是由代码文本中变量声明的位置决定的,闭包指的是一个函数可以访问其词法作用域中的变量,即使这个函数在其词法作用域之外执行。
  • 闭包可以让函数记住并访问其词法作用域,即使这个作用域在函数执行完毕后被销毁。

实际项目中,可以根据具体需求和场景,灵活地使用执行上下文、词法作用域和闭包等概念。

理解这些概念对编程的重要性 💪

理解执行上下文、词法作用域和闭包对编程的重要性主要体现在以下几个方面:

提高代码的可读性和可维护性:理解这些概念有助于更好地理解JavaScript中的变量作用域和函数调用等问题,从而提高代码的可读性和可维护性。

例如,理解词法作用域可以让我们更好地理解以下代码:

function foo() {
  let a = 1;
  function bar() {
    console.log(a); // 输出 1
  }
  bar();
}

foo();

在这个例子中,bar函数在其词法作用域foo之外执行,但仍然可以访问foo作用域中的变量a。理解词法作用域有助于我们更好地理解这个例子。

避免变量污染和冲突:理解执行上下文和词法作用域可以帮助我们更好地管理变量的作用域,避免全局作用域和函数作用域中的变量冲突。

例如,以下代码会导致全局作用域和函数作用域中的变量冲突:

let a = 1;

function foo() {
  let a = 2;
  console.log(a); // 输出 2
}

foo();
console.log(a); // 输出 2

在这个例子中,全局作用域和函数作用域中的变量a冲突,导致输出结果不符合预期。理解执行上下文和词法作用域有助于我们避免这种错误。

实现模块化和封装:闭包可以让函数记住并访问其词法作用域,即使这个作用域在函数执行完毕后被销毁。这使得我们可以将一组相关的函数和变量封装在一个函数内部,然后返回这个函数的引用,这样就可以在其他地方调用这些函数并访问它们需要的变量。

例如,使用闭包实现一个简单的模块:

function createCart() {
  let products = [];

  function addProduct(product) {
    products.push(product);
  }

  function getProducts() {
    return products;
  }

  return {
    addProduct,
    getProducts
  };
}

const cart = createCart();
cart.addProduct({ id: 1, name: 'Product 1' });
console.log(cart.getProducts()); // 输出:[{ id: 1, name: 'Product 1' }]

在这个例子中,createCart函数返回一个闭包,包含addProductgetProducts函数以及它们需要的变量products。这样可以实现模块化,将一组相关的函数和变量封装在一个函数内部。

总之,理解执行上下文、词法作用域和闭包对编程的重要性主要体现在提高代码的可读性和可维护性、避免变量污染和冲突以及实现模块化和封装等方面。实际项目中,可以根据具体需求和场景,灵活地使用这些概念。

实际应用中的注意事项和最佳实践 👀

在实际应用中,关于执行上下文、词法作用域和闭包,有一些注意事项和最佳实践:

使用letconst声明变量:在声明变量时,建议使用letconst而不是varletconst声明的变量具有块级作用域,可以在声明它们的代码块(如for循环、if语句等)内部访问,而var声明的变量具有函数作用域,可以在整个函数内部访问。

例如,以下代码使用let声明变量:

function foo() {
  let a = 1;
  function bar() {
    console.log(a); // 输出 1
  }
  bar();
}

foo();

而以下代码使用var声明变量:

function foo() {
  var a = 1;
  function bar() {
    console.log(a); // 输出 1
  }
  bar();
}

foo();

使用函数执行上下文:在实际项目中,可以使用函数执行上下文来封装一组相关的函数和变量,这样可以实现模块化和封装。

例如,以下代码使用函数执行上下文:

function createCart() {
  let products = [];

  function addProduct(product) {
    products.push(product);
  }

  function getProducts() {
    return products;
  }

  return {
    addProduct,
    getProducts
  };
}

const cart = createCart();
cart.addProduct({ id: 1, name: 'Product 1' });
console.log(cart.getProducts()); // 输出:[{ id: 1, name: 'Product 1' }]

避免全局作用域污染:在实际项目中,避免全局作用域污染非常重要。全局作用域中的变量和函数可能会影响到其他代码,导致难以维护和调试。可以使用闭包来避免全局作用域污染。

例如,以下代码使用闭包避免全局作用域污染:

function createCounter() {
  let count = 0;
  return function() {
    count += 1;
    console.log(count); // 输出 1 2 3
  };
}

const counter = createCounter();
counter();
counter();
counter();

总之,在实际应用中,关于执行上下文、词法作用域和闭包,需要注意使用letconst声明变量,使用函数执行上下文封装相关函数和变量,以及避免全局作用域污染。这些注意事项和最佳实践有助于提高代码的可读性和可维护性,降低代码的耦合度,使代码更加清晰和易于维护。

参考资料

[1]《JavaScript 高级程序设计》
[2] MDN Web Docs: JavaScript

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【PX4SimulinkGazebo联合仿真】在Simulink中使用ROS2控制无人机沿自定义圆形轨迹正向飞行(带偏航角控制)并在Gazebo中可视化

在Simulink中使用ROS2控制无人机沿自定义圆形轨迹正向飞行(带偏航角控制)并在Gazebo中可视化 系统架构Matlab官方例程Control a Simulated UAV Using ROS 2 and PX4 Bridge运行所需的环境配置PX4&Simulink&Gazebo联合仿真实现方法建立Simulink模…

vue3自定义实现悬浮固定按钮组件

目录 一、需求描述二、代码解读三、结果展示 一、需求描述 需要5个固定的悬浮圆,居于页面的右侧。鼠标悬浮在圆上面会显示对应的文字提示其中包含返回顶部悬浮圆,当页面滑至底部时出现,点击页面滑到顶部。点击按钮会给出弹窗 二、代码解读…

LCR 172. 统计目标成绩的出现次数

解题思路&#xff1a;二分查找 题解一 class Solution {public int countTarget(int[] scores, int target) {// 搜索右边界 rightint i 0, j scores.length - 1;while(i < j) {int m (i j) / 2;if(scores[m] < target) i m 1;else j m - 1;}int right i;// 若数…

UE5 C++ Gas开发 学习记录(一)

一个新坑,在TPS的空余时间学习 创建了自己,敌人的BaseCharacter和子类,创建了Gamemode,创建了Controller AuraCharacterBase.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include &…

H264/H265基本编码参数1

本文主要讲解一些视频编码相关的基本概念 像素 像素是图像的基本单元&#xff0c;一个个像素就组成了图像。你可以认为像素就是图像中的一个点。我们来直观地看看像素是怎么组成图像的。在下面这张图中&#xff0c;你可以看到一个个方块&#xff0c;这些方块就是像素。 分辨…

【GameFramework框架内置模块】4、内置模块之调试器(Debugger)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群&#xff1a;398291828 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a;…

开启数字内容创作的新时代

目录 技术解析 未来展望 技术解析 Sora是一款由OpenAI开发的先进AI视频模型&#xff0c;其技术架构基于深度学习和自然语言处理技术。该模型的核心算法原理包括使用深度神经网络进行视频内容的理解、生成和互动。 在技术架构方面&#xff0c;Sora采用了一种混合的神经网络结…

五种多目标优化算法(NSWOA、MOJS、MOAHA、MOPSO、NSGA2)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 1.1NSWOA 1.2MOJS 1.3MOAHA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff0…

15:00面试,15:06就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

EXCEL如何从另一个表查找匹配信息

目录 1.背景&#xff1a;我们有一个目标呈现表&#xff0c;想要从另一个表中查询得到信息&#xff0c;比如根据身份证id查询该id的名字、性别等个人基本信息&#xff0c;或者从另一个财务信息表查询该id的工资信息等&#xff1b; 2.基础方法&#xff1a;利用VLOOKUP函数根据单…

NGINX服务器配置实现加密的WebSocket连接WSS协议

一、背景 最近在做小程序开发&#xff0c;需要在nginx中配置websocket加密模式&#xff0c;即wss。初次配置wss时&#xff0c;踩了两个小时的坑&#xff0c;本文将踩坑过程分享给大家&#xff0c;有需要用到的伙伴可以直接copy即可实现&#xff0c;节省宝贵时间。 二、WebSo…

VS2022调试技巧(一)

什么是bug&#xff1f; 在1945年&#xff0c;美国科学家Grace Hopper在进行计算机编程时&#xff0c;发现一只小虫子钻进了一个真空管&#xff0c;导致计算机无法正常工作。她取出虫子后&#xff0c;计算机恢复了正常&#xff0c;由此&#xff0c;她首次将“Bug”这个词用来描…

用html编写的小广告板

用html编写的小广告板 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</tit…

刘知远LLM——Transformer与预训练模型

文章目录 注意力机制原理介绍注意力机制的各种变式注意力机制的特点 Transformer结构概述Transformer整体结构 输入层byte pair encodingpositional encoding Transformer BlockEncoder BlockMulti-Head Attention Decoder Block其他tricks总结 预训练语言模型语言建模概述预训…

二叉搜索树题目:二叉搜索树中的众数

文章目录 题目标题和出处难度题目描述要求示例数据范围进阶 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 解法三思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉搜索树中的众数 出处&#xff1a;501. 二叉搜索树中的众数 难度 3 级 …

峰值检测电路

常用的峰值检测电路&#xff0c;如下图所示。 该电路有两种工作状态&#xff1a; 1、充电状态&#xff1a;D2导通&#xff0c;D1截止。 当U1的端比-端大时&#xff0c;V1VIN&#xff0c;VCV1-VD2&#xff0c;VOUTVC。这时&#xff0c;给电容C1充电。由于D1截止没有环路&#…

Shell脚本介绍及脚本功能

文章目录 一、什么是shell二、hello word2.1 echo2.2第一个脚本 三、Bash的基本功能3.1别名3.2常用快捷键3.3输入输出3.4 输出重定向3.5 多命令执行3.6 管道符3.7 通配符和特殊符号 一、什么是shell Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。S…

背包问题(介绍+例题+代码+注解)

目录 介绍&#xff1a; 一、01背包 题目描述 输入描述: 输出描述: 代码&#xff1a; 二、完全背包 题目描述 输入描述: 输出描述: 代码&#xff1a; 三、多重背包 题目描述 输入描述: 输出描述: 代码&#xff1a; 四、背包问题 题目描述 输入描述: 输出描…

Mybatis2

Mybatis2 本章目标&#xff1a; myBatis类型别名处理 myBatis参数处理 myBatis结果集类型 myBatis结果集列名和属性名称对应方式处理 附录 本章内容 一、类型别名&#xff08;typeAliases&#xff09;处理 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置…

使用EFCore连接SQLite

简介 在使用EFCore连接SQLite之前我们先来了解一下SQLite SQLite是一个轻量级、自包含、无服务器、零配置的事务性SQL数据库引擎&#xff0c;它支持SQL92标准的大多数查询语言并兼容ACID事务。具体如下&#xff1a; 轻量级&#xff1a;SQLite非常轻巧&#xff0c;它的库体积…