var、let、const和执行上下文

news2024/11/30 0:30:33

在这里插入图片描述

let/const/var

let

基本语法

ES6新增了let命令,用于声明变量,其语法类似于var,但是所声明的变量只在let命令所在的代码块内有效

不存在变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。

暂时性死区

只要块级作用域内存在let命令,他所声明的变量就”绑定“这个区域,不在受外部影响。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上称为”暂时性死区“

不允许重复声明

let 不允许在相同作用域内重复声明同一个变量

const

基本语法

const声明一个只读的常量。一旦声明,常量值就不能改变。
const一旦声明常量,就必须立即初始化,不能留到以后赋值
const不存在变量提升,同样存在暂时性死区,只能在声明后使用,不可重复声明。

本质

const本质上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。
对于简单类型的数据(数值、字符串、布尔值)而言,值就保存在变量指向的内存地址中,因此等同于常量。
但对于复合类型的数据(主要是对象和数组)而言,变量指向的内存地址保存的只是一个指针,const只能保证这个指针是固定的,至于他指向的数据结构是不是可变的,这完全不能控制。
因此,将一个对象声明为常量时必须非常小心。
如果真的想将对象冻结,应该使用Object.freeze方法。

执行上下文

概念

  • 执行上下文是当前 JavaScript 代码被解析和执行时所在环境的抽象概念。

执行上下文的类型

  • 全局执行上下文

这是默认的或基本的执行上下文。任何不在函数内部的代码位于全局执行上下文中。它执行两件事:它创建一个全局对象,它是一个window对象(在浏览器的情况下),并将this的值设置为等于全局对象。一个程序中只能有一个全局执行上下文。

  • 函数执行上下文

每次调用函数时,都会为该函数创建一个全新的执行上下文。每个函数都有自己的执行上下文,但它是在调用或调用(原文是it’s created when the function is invoked or called)函数时创建的。可以有任意数量的函数执行上下文。每当创建一个新的执行上下文时,它都会按照已定义的顺序执行一系列步骤,我将在本文后面讨论这些步骤。

  • Eval 函数执行上下文

在Eval函数内部执行的代码也会获得它自己的执行上下文,但JavaScript开发人员通常不使用Eval

执行上下文包含部分

  1. 在ES3 中
  • scope:作用域,也常常被叫做作用域链。

  • variable object:变量对象,用于存储变量的对象。

  • this value:this 值。

  1. 在ES5 中
  • lexical environment:词法环境,当获取变量时使用。

  • variable environment:变量环境,当声明变量时使用。

  • this value:this 值。

  1. 在ES2018 中, this 值被归入 lexical environment
  • lexical environment:词法环境,当获取变量或者 this 值时使用。
  • variable environment:变量环境,当声明变量时使用
  • code evaluation state:用于恢复代码执行位置。
  • Function:执行的任务是函数时使用,表示正在被执行的函数。
  • ScriptOrModule:执行的任务是脚本或者模块时使用,表示正在被执行的代码。
  • Realm:使用的基础库和内置对象实例。-Generator:仅生成器上下文有这个属性,表示当前生成器。

执行上下文的创建分为两个阶段

一、创建阶段

1、LexicalEnvironment(词法环境) 组件被创建。

2、VariableEnvironment(变量环境) 组件被创建

ExecutionContext = {
  LexicalEnvironment = <ref. to LexicalEnvironment in memory>,
  VariableEnvironment = <ref. to VariableEnvironment in  memory>,
}
词法环境(Lexical Environment)
  1. 环境记录器(Environment Record)

    • 声明性环境记录(Declarative environment record)

      顾名思义,它存储变量和函数声明。
      函数代码的词法环境包含一个声明性环境记录。

    • 对象环境记录(Object environment record)

      全局代码的词法环境包含一个客观环境记录。

      除了变量和函数声明,对象环境记录还存储了一个全局绑定对象(浏览器中的window对象)。

      因此,对于每个绑定对象的属性(在浏览器中,它包含浏览器提供给window对象的属性和方法),记录中会创建一个新条目(new entry)。

  2. 对外部环境的引用(Reference to the outer environment)

    指的是它能够接触到外部的词法环境。这意味着,如果在当前词法环境中没有找到想要查找的变量,JavaScript引擎可以在外部环境中查找它们。

  3. this绑定(This binding.)

    在此组件中,this的值被确定或设置(determined or set)。

    在全局执行上下文中,this的值指向全局对象(在浏览器中,它指的是Window对象)或未定义(在严格模式下)。

    在函数执行上下文中,this的值取决于函数的调用方式。

变量环境 (Variable Environment)

它也是一个词法环境,它的环境记录器(EnvironmentRecord)保存由VariableStatements 在执行上下文中创建的绑定。

如上所述,变量环境也是一个词法环境,因此它具有上述定义的词法环境的所有属性和组件。

在ES6中,词法环境(LexicalEnvironment)组件和变量环境(VariableEnvironment)组件之间的一个区别是,前者用于存储函数声明和变量(let和const)绑定,而后者仅用于存储变量(var)绑定。

二、执行阶段

let a = 20;
const b = 30;
var c;
function multiply(e, f) {
  var g = 20;
  return e * f * g;
}
c = multiply(20, 30);
  1. 当执行上述代码时(the above code is executed),JavaScript引擎创建一个全局执行上下文来执行全局代码。所以在创建阶段,全局执行上下文看起来像这样:
GlobalExectionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      a: < uninitialized > ,
      b: < uninitialized > ,
      multiply: < func >
    }
    outer: < null > ,
    ThisBinding: < Global Object >
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      c: undefined,
    }
    outer: < null > ,
    ThisBinding: < Global Object >
  }
}
  1. 在执行阶段(During the execution phase),完成变量赋值。因此,在执行阶段,全局执行上下文将类似于以下内容。
GlobalExectionContext = {
  LexicalEnvironment: {
      EnvironmentRecord: {
        Type: "Object",
        // Identifier bindings go here
        a: 20,
        b: 30,
        multiply: < func >
      }
      outer: <null>,
      ThisBinding: <Global Object>
    },
  VariableEnvironment: {
      EnvironmentRecord: {
        Type: "Object",
        // Identifier bindings go here
        c: undefined,
      }
      outer: <null>,
      ThisBinding: <Global Object>
    }
  }
  1. 当遇到对function multiply(20,30)的调用时,将创建一个新的函数执行上下文来执行函数代码。所以在创建阶段,函数执行上下文看起来像这样:
FunctionExectionContext = {
LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      Arguments: {0: 20, 1: 30, length: 2},
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  },
VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      g: undefined
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>
  }
}
  1. 在此之后,执行上下文将经历执行阶段(the execution phase),这意味着完成对函数内变量的赋值。所以在执行阶段,函数的执行上下文看起来像这样:
FunctionExectionContext = {
LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      Arguments: {0: 20, 1: 30, length: 2},
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  },
VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // Identifier bindings go here
      g: 20
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>
  }
}

变量提升原理

你可能已经注意到let和const定义的变量在创建阶段没有任何关联的值,但是var定义的变量被设置为undefined。
这是因为,在创建阶段,代码被扫描以查找变量和函数声明,而函数声明被完整地存储在环境中,变量最初被设置为未定义(对于var)或保持未初始化(对于let和const)。
这就是为什么你可以在声明之前访问var定义的变量(虽然未定义),但在声明之前访问let和const变量时会得到引用错误的原因。

顶层对象的属性

顶层对象在浏览器环境中指的是window对象,在Node环境中指的是global对象。在ES5中,顶层对象的属性与全局变量是等价的。

顶层对象的属性与全局变量相关,被认为是JavaScript语言中最大的设计败笔之一。这样的设计带来了几个很大的问题:

  1. 首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);
  2. 其次,程序员很容易不知不觉地就创建了全局变量(比如打字出错);
  3. 最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。

ES6为了改变这一点,

  1. 一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;
  2. 另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。

global对象

ES5的顶层对象,本身也是一个问题,因为它在各种实现里面是不统一的。

  1. 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
  2. 浏览器和 Web Worker 里面,self也指向顶层对象,但是Node没有self。
  3. Node 里面,顶层对象是global,但其他环境都不支持。

同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。

  1. 全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块。
  2. 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
  3. 不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。但是,如果浏览器用了CSP(Content Security Policy,内容安全政策),那么eval、new Function这些方法都可能无法使用。

参考文档

https://juejin.cn/post/7129510217863299102

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

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

相关文章

【部署jar包到服务器】

部署打好的jar包到服务器 首先需要安装对应版本的jdk 查看所有可安装的jdk版本 yum -y list java 选择对应的安装 例如 yum install -y java-1.8.0-openjdk-devel.x86_64 安装好之后&#xff0c;查看jdk版本 java -version 默认安装位置在 usr/lib/jvm之中 倘若你之前的版本不对…

引爆海外市场:ChatGPT带来定制化营销活动的奇迹

在定制一场海外营销活动时&#xff0c;需要首先了解海外市场和定制营销活动的关键是研究目标市场的文化和消费习惯。这包括但不限于&#xff1a; 目标市场的语言和文化背景当地消费者的购买习惯和偏好该领域的市场趋势和竞争情况目标市场的法律法规、行业标准和规范推广渠道和…

编译opencv4.7.0 + opencv_contrib 记录

最近一个项目需要涉及到图像拼接算法&#xff0c;网上了解一番&#xff0c;也大致有思路&#xff1a; 1. 利用surf算法查找特征点 2. 过滤掉一些&#xff0c;获取good点 3. 然后进行配准&#xff08;图像扭曲&#xff09;&#xff0c;对接 4. 形成最终拼接图片 这些工作&a…

NeRF原理简介及实现

“ NeRF&#xff08;Neural Radiance Fields&#xff09;是一种先进的计算机图形学技术&#xff0c;能够使用深度全连接神经网络优化场景的连续5D函数表示&#xff0c;从而生成高度逼真的3D场景。该技术的优势在于没有使用离散化的网格或体素来表示场景&#xff0c;而是使用一个…

【Pandas与SQL系列】Pandas实现分布函数percent_rank、cume_dist

目录 1&#xff0c;分布函数,1.1&#xff0c;percent_rank()1.2&#xff0c;cume_dist()1.3 SQL例子 2&#xff0c;Pandas 实现3&#xff0c;补充Pandas实现排序 1&#xff0c;分布函数, 应用场景&#xff1a;快速查看某个记录所归属的组内的比例 分布函数分类及基础语法&…

asp.net952-sqlserver学生成绩信息管理系统开发

本学生管理系统主要学校内部提供服务&#xff0c;系统分为管理员&#xff0c;教师和学生三部分。 本研究课题重点主要包括了下面几大模块&#xff1a;用户登录&#xff0c;管理员管理,教师信息管理,学生信息管理,课程信息管理,考试信息管理,成绩信息管理系统设置等功能。这几个…

基于深度自编码网络实现轴承故障诊断

1.网络模型(数据集为CWRU) 代码实现了一个基于DAE的分类模型&#xff0c;用于对给定数据集进行分类。首先&#xff0c;通过DAE模型对原始数据进行特征提取和降维&#xff0c;然后使用分类模型将提取的特征与标签相匹配&#xff0c;以便对新数据进行分类。 代码的主要流程: 导…

用激光点云估算建筑高度【PDAL|PostgreSQL】

LiDAR 数据可以非常强大地提取城市规模的地面和物体的高程。 在 One Concern&#xff0c;我们正在使用 LiDAR 数据提取地面和建筑物高程&#xff0c;以改进进入我们的自然灾害模型的暴露信息&#xff0c;最终估计洪水和地震的影响。 由于 3DEP 项目预计将在 2023 年之前收集全…

STM32------GPIO

GPIO 一、介绍 1、1 什么是GPIO&#xff1f; 输入输出端口 1、2 GPIO特点 1、不同封装IO数量不一样。 2、快速翻转&#xff0c;每次翻转最快只需要两个时钟周期。 3、每个IO都可以做中断。 4、支持8种工作模式。 1、3 GPIO电气特性 STM32工作电压范围&#xff1a;2~3…

【C进阶】通讯录的实现(静态+动态)

目录 前言: 一.静态通讯录的实现 1.关于通讯录的前期准备 (1)菜单的打印 (2)建立一个联系人的信息 (3)通讯录整体 (4)宏定义常量 (5)主函数菜单选项的功能 2.通讯录的功能实现 (1)初始化通讯录 (2)增加指定联系人 (3) 展示通讯录 "FindByName函数" (4)删…

Autosar 规范接口之SPI

Autosar SPI 概述&#xff08;Specification of SPI Handler/Driver &#xff09; 基础知识介绍 在AutoSar标准中&#xff0c;与SPI通讯相关的三个术语&#xff1a;Channel、Job和Sequence。 1个Channel对应1个发送缓冲区和1接收缓冲区&#xff1b;1个Job对应着1次SPI通讯发送…

(第45册)HTML5网页游戏设计从基础到开发(第2版·微课视频版)

HTML5是W3C组织近年来发布的一项引起业内轰动的Web新标准。它几乎颠覆现有Web应用, HTML5从根本上改变了开发商开发web应用的方式,从桌面浏览器到移动应用,这种语言和标准都正在影响将继续影响着各种操作平台。 本书是第2版&#xff0c;第1版2018年出版&#xff0c;经历6次印刷…

【项目开发】GoFrame+Vue项目部署到阿里云服务器

前言 本来想都用docker部署的&#xff0c;结果学艺实在是不精&#xff0c;只能先这么委曲求全宝塔页面的反向代理一直无法生效&#xff0c;用了重定向跳转页面宝塔的网站也可以构建go项目 背景 后端使用GoFrame框架&#xff0c;前端使用Vue 3 TypeScript Vite&#xff0c;…

Windows Cygwin 配置

Windows Cygwin 配置 一、什么是Cygwin&#xff1f; Cygwin&#xff0c;原Cygnus出品&#xff08;已被红帽收购&#xff09;&#xff0c;目前是RedHat名下的项目。项目的目的是提供运行于 Windows 平台的类 Unix 环境&#xff08;以 GNU 工具为代表&#xff09;。为了达到这个…

learn C++ NO.4 ——类和对象(2)

1.类的6个默认成员函数 1.1.默认成员函数的概念 在 C 中&#xff0c;如果没有显式定义类的构造函数、析构函数、拷贝构造函数和赋值运算符重载函数&#xff0c;编译器会自动生成这些函数&#xff0c;这些函数被称为默认成员函数。 class Date { };初步了解了默认成员函数&am…

pytorch实战10:基于pytorch简单实现CGAN

基于pytorch简单实现CGAN 前言 ​ 最近在看经典的卷积网络架构&#xff0c;打算自己尝试复现一下&#xff0c;在此系列文章中&#xff0c;会参考很多文章&#xff0c;有些已经忘记了出处&#xff0c;所以就不贴链接了&#xff0c;希望大家理解。 ​ 完整的代码在最后。 本系列…

离散数学下 ---格与布尔代数

&#xff08;一&#xff09;目录 格的定义及性质 子格 分配格 有补格 布尔代数 &#xff08;二&#xff09; 内容 格的定义与性质 补充点&#xff1a; 格与布尔代数&#xff0c;它们与群的基本不同之处是&#xff1a;格与布尔代数的基集都是一个偏序集。 格是一个具…

华硕主板win11设置关机状态下USB接口不通电

华硕主板win11设置关机状态下USB接口不通电 我新装机子在关机之后usb还是通电&#xff0c;导致一些外接设备显示灯常亮着非常不方便。因此我尝试把其关掉。 我的是华硕主板&#xff0c;不同主板可能设置方式不一样&#xff0c;请注意。 请按照如下步骤操作&#xff1a; 计算机…

NetApp FAS2554故障灯常亮case处理过程分享

近期处理了一个NetApp FAS2554前面故障灯一直点亮的case&#xff0c;本文对于分析过程和最终的问题发现做一个分享&#xff0c;欢迎讨论&#xff0c;可以add wechat at StorageExpert。 外观检查&#xff1a; 客户反馈&#xff0c;一套FAS2554存储&#xff0c;没有任何扩展柜…

文献阅读(52)—— Integration self-attention and convolution

文献阅读&#xff08;52&#xff09;—— Integration self-attention and convolution 文章目录 文献阅读&#xff08;52&#xff09;—— Integration self-attention and convolution先验知识/知识拓展文章结构背景文章方法1. Relating Self-Attention with Convolution 文章…