JS进阶-作用域

news2024/12/26 4:35:00

学习目标:

  • 掌握作用域

学习内容:

  1. 作用域
  2. 局部作用域
  3. 全局作用域
  4. 作用域链
  5. JS垃圾回收机制
  6. 拓展-JS垃圾回收机制-算法说明
  7. 闭包
  8. 变量提升

作用域:

作用域规定了变量能够被访问的"范围",离开了这个"范围"变量便不能被访问。
作用域分为:

  1. 局部作用域
  2. 全局作用域

局部作用域:

局部作用域分为函数作用域和块作用域。

  • 函数作用域:

在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

 <script>
    function getSum() {
      //函数内部是函数作用域  属于局部变量
      const num = 10
    }
    console.log(num)  //此处报错,函数外部不能使用局部作用域变量
  </script>

总结:

  1. 函数内部声明的变量,在函数外部无法被访问。
  2. 函数的参数也是函数内部的局部变量。
  3. 不同函数内部声明的变量无法互相访问。
  4. 函数执行完毕后,函数内部的变量实际被清空了。
  • 块级作用域:

在JavaScript中使用{ }包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。

 <script>
    // for (var i = 1; i <= 3; i++) {
    //   console.log(i)
    // }
    // console.log(i)

    // for (let i = 1; i <= 3; i++) {
    //   // 块作用域
    //   console.log(i)
    // }
    // for (let i = 1; i <= 3; i++) {
    //   // 块作用域
    //   console.log(i)
    // }

    if (true) {
      let i = 10
    }
    console.log(i)  //报错,外部无法被访问到
  </script>

总结:

  1. let声明的变量会产生块级作用域,var不会产生块级作用域。
  2. const声明的常量也会产生块作用域。
  3. 不同代码之间的变量无法互相访问。
  4. 推荐使用letconst
  • 小结:

1.局部作用域分为哪两种?

局部作用域说明
函数作用域函数内部
块级作用域{ }

2.局部作用域声明的变量外部能使用吗?

不能

全局作用域:

<script>标签.js文件的【最外层】就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。

全局作用域中声明的变量,任何其它作用域都可以被访问。

 <script>
    //全局作用域
    //全局作用域下声明了num变量
    const num = 10
    function fn() {
      //函数内部可以使用全局作用域的变量
      console.log(num)
    }
    //此处全局作用域
  </script>

注意:

  1. 为window对象动态添加的属性默认也是全局的,不推荐!!!
  2. 函数中未使用任何关键字声明的变量为全局变量,不推荐!!!!
  3. 尽可能少的声明全局变量,防止全局变量被污染。
  • 小结:

1.全局作用域有哪些?

<script>标签内部-
.js文件-

2.全局作用域声明的变量其他作用域能使用吗?

相当能

JavaScript中的作用域是程序被执行时的底层机制,了解这一机制有助于规范代码书写习惯,避免因作用域导致的语法错误。


作用域链:

作用域本质上是底层的变量查找机制

在函数被执行时,会优先查找当前函数作用域中查找变量。

如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域。

 <script>
    //全局作用域
    let a = 1
    let b = 2
    //局部作用域
    function f() {
      let a = 1
      //局部作用域
      function g() {
        a = 2
        console.log(a)
      }
      g() //调用g
    }
    f() //调用f
  </script>

从小到大
总结:

  1. 嵌套关系的作用域串联起来形成了作用域链。
  2. 相同作用域链中按着从小到大的规则查找变量。
  3. 子作用域能够访问父作用域,父级作用域无法访问子级作用域。
  • 小结:

1.作用域链本质是什么?

作用域本质上是底层的变量查找机制。

2.作用域查找的规则是什么?

会优先查找当前函数作用域中查找变量。
查找不到则会依次逐级查找父级作用域直到全局作用域。

JS垃圾回收机制:

垃圾回收机制简称GC。

JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。

  • 内存的生命周期:

JS环境中分配的内存,一般有如下生命周期

  1. 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存。
  2. 内存使用:即读写内存,也就是使用变量、函数等。
  3. 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存。
  • 说明:

全局变量一般不会回收(关闭页面回收)。

一般情况下局部变量的值,不用了,会被自动回收掉。

  • 内存泄漏:程序中分配的内存由于某种原因程序未释放无法释放叫做内存泄漏
<script>
    for (let i = 1; i <= 3; i++) {
 
    }
    let num = 10
    function fn() {
      const str = 'andy'
      // str = 'lily'
      console.log(str)
    }
    fn()
    fn()
    fn()
  </script>
  • 小结:

1.什么是垃圾回收机制?

简称GC。
JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。

2.什么是内存泄漏?

不再用到的内存,没有及时释放,就叫做内存泄漏。

3.内存的生命周期是什么样的?

内存分配、内存使用、内存回收。
全局变量一般不会回收;一般情况下局部变量的值,不用了,会被自动回收掉。

拓展-JS垃圾回收机制-算法说明:

堆栈空间分配区别:

  1. 栈(操作系统):由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面。
  2. 堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面。

下面介绍两种常见的浏览器垃圾回收算法:引用计数法标记清除法

  • 引用计数:

IE采用的引用计数算法,定义“内存不再使用”,就是看一个对象是否有指向它的引用,没有引用了就回收对象。

算法:

  1. 跟踪记录被引用的次数
  2. 如果被引用了一次,那么就记录次数1,多次引用会累加 ++
  3. 如果减少一个引用就减1 --
  4. 如果引用次数是0,则释放内存。

在这里插入图片描述
在这里插入图片描述
由上面可以看出,引用计数算法是个简单有效的算法。

但它却存在一个致命的问题:嵌套引用(循环引用)。

如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄漏。

在这里插入图片描述

因为他们的引用次数永不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄漏。

  • 标记清除法:

现代的浏览器已经不再使用引用计数算法了。

现代浏览器通用的大多是基于标记清除算法的某些改进算法,总体思想都是一致的。

核心:

  1. 标记清除算法将“不再使用的对象”定义为“无法达到的对象”。
  2. 就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。
  3. 那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收

在这里插入图片描述
在这里插入图片描述
根部已经访问不到,所以自动清除。

  • 小结:

1.标记清除法核心思路是什么?

从根部扫描对象,能查找到的就是使用的,查找不到的就要回收。

闭包:

概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。

简单理解:闭包 = 内层函数 + 外层函数的变量

  • 闭包作用:封闭数据,提供操作,外部也可以访问函数内部的变量。
<script>
    // //简单的写法
    // function outer() {
    //   let a = 10
    //   function fn() {
    //     console.log(a)
    //   }
    //   fn()
    // }
    // outer()


    //常见的闭包的形式  外部可以访问使用  函数内部的变量
    function outer() {
      let a = 10
      function fn() {
        console.log(a)
      }
      return fn
    }

    // outer() === fn ===  function fn() {}
    // const fun = function fn(){}
    // const fun = outer()

    //常见的写法2
    // function outer() {
    //   let a = 100
    //   return function () {
    //     console.log(a)
    //   }
    // }
    // const fun = outer()
    // fun()  // 调用函数

    //外面要使用这个10
 </script>
  • 闭包应用:实现数据的私有。
<script>
 //闭包的应用
    //普通形式  统计函数调用的次数
    // let i = 0
    // function fn() {
    //   i++
    //   console.log(`函数被调用了${i}次`)
    // }
    //因为i是全局变量,容易被修改
    
    //闭包形式 统计函数调用的次数
    function count() {
      let i = 0
      function fn() {
        i++
        console.log(`函数被调用了${i}`)
      }
      return fn
    }
    const fun = count()
  </script>
  • 小结:

1.怎么理解闭包?

闭包 = 内层函数 + 外层函数的变量。

2.闭包的作用?

封闭数据,实现数据私有,外部也可以访问函数内部的变量。
闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。

3.闭包也可能引起的问题?

内存泄漏。

变量提升:

变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)。

  • 注意:
  1. 变量在未声明即被访问时会报语法错误。
  2. 变量在var声明之前即被访问,变量的值为undefined
  3. let/const 声明的变量不存在变量提升。
  4. 变量提升出现在相同作用域当中。
  5. 实际开发中推荐先声明再访问变量
<script>
    // 1. 把所有var声明的变量提升到 当前作用域的最前面
    // 2. 只提升声明, 不提升赋值
    // var num
    // console.log(num + '件')
    // num = 10
    // console.log(num)

    function fn() {
      console.log(num)
      var num = 10
    }
    fn()
  </script>
  • 说明:

JS初学者经常花很多时间才能习惯变量提升,还经常出现一些意想不到的bug,正因为如此,ES6 引入了块级作用域,用let 或者 const声明变量,让代码写法更加规范和人性化。

  • 小结:

1.用哪个关键字声明变量会有变量提升?

  var

2.变量提升是什么流程?

先把var变量提升到当前作用域于最前面。
只提升变量,不提升变量赋值。
然后依次执行代码。

我们不建议使用var声明变量。

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

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

相关文章

论文1:多模态人类活动识别综述

论文题目&#xff1a;A Review of Multimodal Human Activity Recognition with Special Emphasis on Classification, Applications, Challenges and Future Directions 文献偏旧-2021 1、 专业词汇&#xff1a; Human activity recognition (HAR)-人类活动识别 Wearable …

Open3D 计算点云的马氏距离

目录 一、概述 1.1原理 1.2应用 二、代码实现 三、实现效果 3.1原始点云 3.2计算后点云 一、概述 1.1原理 马氏距离&#xff08;Mahalanobis Distance&#xff09;是一种度量多维数据点与数据分布中心之间距离的方法。与欧几里得距离不同&#xff0c;马氏距离考虑了数据…

树目标、抓过程、要结果

一个好的管理理念不会因为一两个成功案例而发扬&#xff0c;一定是有无数个案例验证了它的价值所在&#xff0c;既然OKR在国外已经取得成功&#xff0c;那么国内依然如此。那么OKR这么成功&#xff0c;它到底好在哪呢&#xff1f; 一、OKR是连接企业战略和落地执行的最佳方式。…

C嘎嘎:类和对象(上)

目录 面向过程和面向对象的初步认识 类的引入 类的定义 类的访问限定符及封装 访问限定符 封装 类的作用域 类的实例化 类对象模型 如何计算类对象大小 结构体内存对齐规则 this指针 this指针的引出 this指针的特性 面向过程和面向对象的初步认识 C语言是面向过程…

CentOS 6.5配置国内在线yum源和制作openssh 9.8p1 rpm包 —— 筑梦之路

CentOS 6.5比较古老的版本了&#xff0c;而还是有一些古老的项目仍然在使用。 环境说明 1. 更换国内在线yum源 CentOS 6 在线可用yum源配置——筑梦之路_centos6可用yum源-CSDN博客 cat > CentOS-163.repo << EOF [base] nameCentOS-$releasever - Base - 163.com …

尚品汇-(十二)

&#xff08;1&#xff09;数据库表结构 根据以上的需求&#xff0c;以此将SKU关联的数据库表结构设计为如下&#xff1a; base_attr_value&#xff1a;前面学的平台属性值表 我们进行关联&#xff0c;可以从分类导向平台&#xff0c;通过平台过滤商品 &#xff08;2&#xf…

利用亚马逊云科技云原生Serverless代码托管服务开发OpenAI ChatGPT-4o应用

今天小李哥继续介绍国际上主流云计算平台亚马逊云科技AWS上的热门生成式AI应用开发架构。上次小李哥分享​了利用谷歌云serverless代码托管服务Cloud Functions构建Gemini Pro API​&#xff0c;这次我将介绍如何利用亚马逊的云原生服务Lambda调用OpenAI的最新模型ChatGPT 4o。…

【NTN 卫星通信】Starlink基于终端用户的测量以及测试概述

1 概述 收集了一些starlink的资料&#xff0c;是基于终端侧部署在野外的一些测试以及测量结果。 2 低地球轨道卫星网络概述 低地球轨道卫星网络(lsn)被认为是即将到来的6G中真正实现全球覆盖的关键基础设施。本文介绍了我们对Starlink端到端网络特征的初步测量结果和观测结果&…

基于YOLOv9的脑肿瘤区域检测

数据集 脑肿瘤区域检测&#xff0c;我们直接采用kaggle公开数据集&#xff0c;Br35H 数据中已对医学图像中脑肿瘤位置进行标注 数据集我已经按照YOLO格式配置好&#xff0c;数据内容如下 数据集中共包含700张图像&#xff0c;其中训练集500张&#xff0c;验证集200张 模型训…

DHCP与TCP的简单解析

目录 一、DHCP 1.1 DHCP概述 1.2 DHCP的优势 1.3 DHCP的模式与分配方式***** 1.3.1 DHCP的模式&#xff1a;C/S模式&#xff08;客户机与服务器模式&#xff09; 1.3.2 DHCP的分配方式 1.4 DHCP的租约过程及原理 1.4.1 DHCP的工作原理***** 1.4.2 更新租约原理***** …

D - Go Stone Puzzle(abc361)

分析&#xff1a;因为n很小&#xff0c;可以逐一搜索&#xff0c;用一个队列将每种情况列出来&#xff0c;用bfs寻找从s到t的最短路径 #include <bits/stdc.h> using namespace std; int n; string s, t; map<string, int> dis; void bfs() { dis[s] 0; …

加密与安全_常见的分组密码 ECB、CBC、CFB、OFB模式介绍

文章目录 Pre概述why分组密码和流密码的基本概念什么是模式分组密码的常见模式1. ECB 模式&#xff08;电子密码本模式&#xff09;2. CBC 模式&#xff08;密文分组链接模式&#xff09;3. CFB 模式&#xff08;密文反馈模式&#xff09;4. OFB 模式&#xff08;输出反馈模式&…

MySQL安装时initializing database失败

问题页面&#xff1a; 解决方法&#xff1a; 1.勾选红框中的选项&#xff1a; 2.将下图红框中全部改为英文&#xff1a; 然后一路next就可以了。

VRay渲染有什么技巧?渲染100邀请码1a12

渲染是视觉行业非常重要的一环&#xff0c;没有渲染就没有效果图&#xff0c;常用的渲染器有Vray&#xff0c;而Vray渲染有很多技巧&#xff0c;可以让渲染更快更省&#xff0c;下面我们总结下。 1、删除无用对象 检查场景&#xff0c;看是否有一些不需要渲染的物体和灯光&am…

读人工智能全传06逻辑编程

1. 现代逻辑 1.1. 到了20世纪初&#xff0c;现代逻辑的基本框架已经大致建立起来&#xff0c;当时确立的逻辑运算系统&#xff0c;直至如今仍然能够支撑数学家几乎所有的逻辑推理工作 1.1.1. 这个系统被称为一阶逻辑&#xff0c;一阶逻辑是数学和推理的通用语言 1.1.2. 这个…

BaseServlet的封装

创建BaseServlet的必要性 如果不创建BaseServlet&#xff0c;现在我们只要实现一个功能&#xff0c;我们就需要创建一个servlet! 例如:用户模块(登录&#xff0c;注册&#xff0c;退出录&#xff0c;激活&#xff0c;发送邮件等等功能) 也就是说&#xff0c;我们必须要创建一…

工程化-vue3+ts:代码检测工具 ESLint

一、理解ESLint ESLint是一个开源的JavaScript代码检查工具&#xff0c;用于帮助开发人员规范和统一编码风格。它可以检查代码中的潜在错误、不一致的编码习惯以及一些常见的代码问题。 ESLint使用基于规则的插件体系&#xff0c;可以根据项目的需求和个人的偏好配置不同的规…

数学系C++ 类与对象 STL(九)

目录 目录 面向对象&#xff1a;py&#xff0c;c艹&#xff0c;Java都是,但c是面向过程 特征&#xff1a; 对象 内敛成员函数【是啥】&#xff1a; 构造函数和析构函数 构造函数 复制构造函数/拷贝构造函数&#xff1a; 【……】 实参与形参的传递方式&#xff1a;值…

git杂记

git 安装&#xff1a; 在 Windows 上安装 Git 也有几种安装方法。 官方版本可以在 Git 官方网站下载。 打开 https://git-scm.com/download/win&#xff0c;下载会自动开始。 要注意这是一个名为 Git for Windows 的项目&#xff08;也叫做 msysGit&#xff09;&#xff0c;和…

如何优化 PostgreSQL 中对于树形结构数据的查询?

文章目录 一、数据模型选择&#xff08;一&#xff09;邻接表模型&#xff08;二&#xff09;路径枚举模型&#xff08;三&#xff09;嵌套集模型 二、索引策略&#xff08;一&#xff09;对于邻接表模型&#xff08;二&#xff09;对于路径枚举模型&#xff08;三&#xff09;…