JavaScript 进阶 (一)

news2024/11/28 22:41:42

目录

作用域

局部作用域

函数作用域

块作用域

全局作用域

作用域链

JS垃圾回收机制

闭包

变量提升

函数进阶

函数提升

函数参数

箭头函数

基本语法

箭头函数参数

箭头函数this

解构赋值

数组解构

对象解构

遍历数组 forEach 方法(重点)

筛选数组 filter 方法(重点)


作用域

作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问,作用域分为全局作用域和局部作用域。

局部作用域

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

函数作用域

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

总结:

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

块作用域

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

JavaScript 中除了变量外还有常量,常量与变量本质的区别是【常量必须要有值且不允许被重新赋值】,常量值为对象时其属性和方法允许重新赋值。

总结:

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

注:开发中 let 和 const 经常不加区分的使用,如果担心某个值会不小被修改时,则只能使用 const 声明成常量。

全局作用域

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

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

总结:

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

作用域链

作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域

总结:

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

JS垃圾回收机制

垃圾回收机制(Garbage Collection) 简称 GC

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

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

内存的生命周期

JS环境中分配的内存, 一般有如下生命周期:
1. 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
2. 内存使用:即读写内存,也就是使用变量、函数等
3. 内存回收:使用完毕,由垃圾回收自动回收不再使用的内存
4. 说明:
  • 全局变量一般不会回收(关闭页面回收);
  • 一般情况下局部变量的值, 不用了, 会被自动回收掉

算法说明

堆栈空间分配区别:
  1.  栈(操作系统): 由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面。
  2. 堆(操作系统): 一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放到堆里面。
l
引用计数
IE采用的引用计数算法, 定义“ 内存不再使用 ”,就是看一个 对象 是否有指向它的引用,没有引用了就回收对象
算法:
  1. 跟踪记录被引用的次数
  2. 如果被引用了一次,那么就记录次数1,多次引用会累加 ++
  3.  如果减少一个引用就减1 --
  4. 如果引用次数是0 ,则释放内存

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

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

标记清除法

现代的浏览器已经不再使用引用计数算法了。
现代浏览器通用的大多是基于 标记清除算法 的某些改进算法,总体思想都是一致的
核心:
  1. 标记清除算法将“不再使用的对象”定义为“无法达到的对象”。
  2. 就是从根部(在JS中就是全局对象)出发定时扫描内存中的对象。 凡是能从根部到达的对象,都是还需要使用的。
  3. 那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收

闭包

概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解: 闭包 =  内层函数 + 外层函数的变量
闭包作用: 封闭数据,提供操作,外部也可以访问函数内部的变量
闭包的基本格式:
 function outer() {
    let a = 100
    function fn() {
         console.log(a)
       }
     return fn
   }
闭包应用: 实现数据的私有
统计函数调用的次数
function count() {
      let i = 0
      function fn() {
        i++
        console.log(`函数被调用了${i}次`)
      }
      return fn
    }
    const fun = count()

此时变量 i  理应是局部变量中被 会被回收,但外部函数要使用到变量i ,所以不会被回收,垃圾回收器不会进行回收,导致内存泄露

 

变量提升

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

1. 把所有var声明的变量提升到 当前作用域的最前面

2. 只提升声明, 不提升赋值

总结:

  1. 变量在未声明即被访问时会报语法错误
  2. 变量在声明之前即被访问,变量的值为 undefined
  3. let 声明的变量不存在变量提升,推荐使用 let
  4. 变量提升出现在相同作用域当中
  5. 实际开发中推荐先声明再访问变量

注:关于变量提升的原理分析会涉及较为复杂的词法分析等知识,而开发中使用 let 可以轻松规避变量的提升,

函数进阶

函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
<script>
    var fun
    //1. 会把所有函数声明提升到当前作用域的最前面
    //2. 只提升函数声明,不提升函数调用
    fn()
    function fn() {
      console.log('函数提升')
    }
    fun()
    var fun = function () {
      console.log('函数表达式')
    }
      //函数表达式 必须先声明和赋值, 后调用 否则 报错
  </script>
总结:
  1. 函数提升能够使函数的声明调用更灵活
  2. 函数表达式不存在提升的现象
  3. 函数提升出现在相同作用域当中

函数参数

动态参数
arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
 <script>
    function getSum() {
      // console.log(arguments)  [2,3,4]
      let sum = 0
      for (let i = 0; i < arguments.length; i++) {
        sum += arguments[i]
      }
      console.log(sum)
    }
    getSum(2, 3, 4)
  </script>

总结:
  1. arguments 是一个伪数组,只存在于函数中
  2. arguments 的作用是动态获取函数的实参
  3. 可以通过for循环依次得到传递过来的实参

剩余参数

1. ... 是语法符号,置于最末函数形参之前,用于获取 多余 的实参
2. 借助 ... 获取的剩余实参,是个 真数组
<script>
  function config(baseURL, ...other) {
    console.log(baseURL) // 得到 'http://baidu.com'
    console.log(other)  // other  得到 ['get', 'json']
  }
  // 调用函数
  config('http://baidu.com', 'get', 'json');
</script>

 展开运算符

展开运算符(…),将一个数组进行展开
说明:
1. 不会修改原数组
典型运用场景: 求数组最大值(最小值)、合并数组等
const arr1 = [1, 2, 3]
    // 展开运算符 可以展开数组
    // console.log(...arr)

    // console.log(Math.max(1, 2, 3))
    // ...arr1  === 1,2,3
    // 1 求数组最大值
    console.log(Math.max(...arr1)) // 3
    console.log(Math.min(...arr1)) // 1

箭头函数

目的: 引入箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁
使用场景: 箭头函数更适用于那些本来 需要匿名函数的地方

基本语法

语法1:基本写法

1. 箭头函数 基本语法
    const fn = () => {
      console.log(123)
      }
     fn()

语法2:只有一个参数可以省略小括号

// 2. 只有一个形参的时候,可以省略小括号
     const fn = x => {
       console.log(x)
     }
     fn(1)

 语法3:如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值

 // const fn = x => x + x
    // console.log(fn(1))

语法4:加括号的函数体返回对象字面量表达式

// const fn = (uname) => ({ uname: uname })
    // console.log(fn('刘德华'))

总结:

  1. 箭头函数属于表达式函数,因此不存在函数提升
  2. 箭头函数只有一个参数时可以省略圆括号 ()
  3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回

箭头函数参数

1. 普通函数有arguments 动态参数
2. 箭头函数 没有 arguments 动态参数,但是 有 剩余参数 ..args
script>
    // 1. 利用箭头函数来求和
    const getSum = (...arr) => {
      let sum = 0
      for (let i = 0; i < arr.length; i++) {
        sum += arr[i]
      }
      return sum
    }
    const result = getSum(2, 3, 4)
    console.log(result) // 9
  </script>

箭头函数this

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。

在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window,因此
DOM事件回调函数为了简便,还是不太推荐使用箭头函数

解构赋值

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值

数组解构

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。

基本语法:

  1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
  2. 变量的顺序对应数组单元值的位置依次进行赋值操作

典型应用交互2个变量

// 交换2个变量的值
    let a = 1
    let b = 2;
    [b, a] = [a, b]
    console.log(a, b)

注意: js 前面必须加分号情况

1. 立即执行函数

2. 数组解构

1.变量多 单元值少的情况:

变量的数量大于单元值数量时,多余的变量将被赋值为 undefined

2. 变量少 单元值多的情况:

3. 利用剩余参数解决变量少 单元值多的情况:

剩余参数返回的还是一个数组

4. 防止有undefined传递单元值的情况,可以设置默认值:

允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效

5. 按需导入,忽略某些返回值:

6. 支持多维数组的结构:

总结:

  1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
  2. 变量的顺序对应数组单元值的位置依次进行赋值操作
  3. 变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
  4. 变量的数量小于单元值数量时,可以通过 ... 获取剩余单元值,但只能置于最末位
  5. 允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效 

对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法

1. 基本语法:

  1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
  2. 对象属性的值将被赋值给与属性名相同的变量
  3. 注意解构的变量名不要和外面的变量名冲突否则报错
  4. 对象中找不到与变量名一致的属性时变量值为 undefined

2.给新的变量名赋值:
可以从一个对象中提取变量并同时修改新的变量名

 

2. 数组对象解构

// 2. 解构数组对象
    const pig = [
      {
        uname: '佩奇',
        age: 6
      }
    ]
    const [{ uname, age }] = pig
    console.log(uname)
    console.log(age)
3. 多级对象解构:
 // // 多级对象解构
    const { name, family: { mother, father, sister } } = pig

后台传递过来的数据  只选择data  将msg 解构  然后带入参数

 function render({ data }) {
      // const { data } = arr
      // 我们只要 data 数据
      // 内部处理
      console.log(data)

    }
    render(msg)

遍历数组 forEach 方法(重点)

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数

主要使用场景: 遍历数组的每个元素

语法:

 

 // forEach 就是遍历  加强版的for循环  适合于遍历数组对象
    const arr = ['red', 'green', 'pink']
    const result = arr.forEach(function (item, index) {
      console.log(item)  // 数组元素 red  green pink
      console.log(index) // 索引号
    })
    // console.log(result)

筛选数组 filter 方法(重点)

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
主要使用场景: 筛选数组符合条件的元素 ,并返回筛选之后元素的新数组
语法:
 <script>
    const arr = [10, 20, 30]
    // const newArr = arr.filter(function (item, index) {
    //   // console.log(item)
    //   // console.log(index)
    //   return item >= 20
    // })
    // 返回的符合条件的新数组

    const newArr = arr.filter(item => item >= 20)
    console.log(newArr)
  </script>
filter() 筛选数组
返回值: 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组
  参数: currentValue 必须写, index 可选
  因为返回新数组,所以不会影响原数组

 

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

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

相关文章

shell SNAT与DNAT

文章目录 SNATSNAT原理与应用SNAT实验 DNATDNAT原理与应用DNAT实验 SNAT SNAT原理与应用 SNAT 应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xff08;私有不能早Internet中正常路由&#xff09; SNAT原理&#xff1a;修改数据包的源地址。 SNAT转换前提…

文心一言 VS 讯飞星火 VS chatgpt (23)-- 算法导论4.2 5题

五、V.Pan 发现一种方法&#xff0c;可以用 132 464 次乘法操作完成 68 x 68 的矩阵相乘&#xff0c;发现另一种方法&#xff0c;可以用 143 640 次乘法操作完成 70 x 70 的矩阵相乘&#xff0c;还发现一种方法&#xff0c;可以用155 424次乘法操作完成 72 x 72 的矩阵相乘。当…

数据安全治理科技产品能力-数据安全复合治理框架和模型解读(2)

数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地数据安全治理科技水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理…

自动驾驶业内动态简讯

1. 引言 参与自动驾驶领域相关研发工作已有多年&#xff0c;针对该领域的快速发展&#xff0c;收集业内各大科技公司最新进展和技术突破&#xff0c;供伙伴们交流探讨。 闲话少说&#xff0c;直接开始吧! 2. 博世 据新闻介绍&#xff0c;博世在德国道路上测试L4级无人驾驶汽…

java 区分缺陷Defects/感染Infections/失败Failure

java 区分缺陷Defects/感染Infections/失败Failure 缺陷Defects 软件故障总是从代码中一个或多个缺陷的执行开始。 缺陷只是一段有缺陷、不正确的代码。 缺陷可能是程序语句的一部分或完整部分&#xff0c;也可能对应于不存在但应该存在的语句。 尽管程序员要对代码中的缺陷负…

基于SSM的甜品店商城系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着社会经济的发展和…

Altium Designer 相同电路多组复制布线

在进行设计开发的时候&#xff0c;总会遇到相同的电路&#xff0c;或者模块&#xff0c;这些电路可以使用相同的布局和走线。我们可以画好其中一部分&#xff0c;然后直接复制&#xff0c;就可以提高效率。下面记录我自己的实际操作过程&#xff0c;有一些地方遇到了问题&#…

Android | Android OS 源码结构

参考&#xff1a;AndroidXRef (http://androidxref.com/)版本&#xff1a;Pie - 9.0.0_r3 整体结构 对于 Android OS 的源码目录来说&#xff0c;各个版本的结构大同小异&#xff0c;随不同版本特性会有个别目录差异。编译后会额外产生一个 out 文件夹用于存储编译产生的文件。…

Unity使用SteamVR2.0实现基本功能(瞬移,抓取物品,射线点击,UI交互等)

基础设置 把SteamVR的Player预制件拖到一个空场景,删掉场景内原本的相机 一.瞬移 新建一个Plane,当做地板找到SteamVR的人物瞬移控制器 Teleporting ,把它拖到场景里 1. 范围移动 我们需要在可以移动的区域,也就是碰撞器上,挂TeleportArea脚本 这个脚本会自动修改你的材质球…

抖音seo源码--开源,支持二开不加密

抖音seo源码&#xff0c;抖音seo矩阵系统源码技术搭建&#xff0c;抖音seo源码技术开发思路梳理搭建 开发思路&#xff1a; 抖音seo源码如何搭建&#xff1f;抖音seo排名优化系统软件部分源码分析&#xff0c;代码打包中。。。 场景&#xff1a;在 python 中&#xff0c;你可…

windows下修改PyCharm默认terminal 在Git Bash中使用conda

windows下修改PyCharm默认terminal & 在Git Bash中使用conda windows下修改PyCharm默认terminal在Git Bash中使用conda windows下修改PyCharm默认terminal PyCharm的terminal默认使用的是powershell&#xff0c;但是conda环境是通过cmd运行的&#xff0c;因此可以将PyChar…

安捷伦N5182A是德KEYSIGHT N5182B 100KHZ至3G/6G信号发生器

Agilent N5182A、Keysight N5182A MXG 射频矢量信号发生器&#xff0c;100 kHz - 3 GHz 或 6 GHz ​Keysight N5182A (Agilent) MXG 射频矢量信号发生器具有快速频率、幅度和波形切换、带电子衰减器的高功率和高可靠性 – 所有这些都集成在两个机架单元 (2RU) 中。Keysight N5…

H743 USBHOST协议栈 CPU占用率高的问题。

经过查看&#xff0c;是因为USBHOST频繁的进入中断导致&#xff0c;单步执行发现&#xff0c;是因为发生了USB_OTG_HCINT_CHH或者USB_OTG_HCINT_NAK中断了&#xff0c;只在CHH中断服务函数里&#xff0c;给USB主线程发了1个消息&#xff0c;又引起了USBH_Process_OS主线程的频繁…

YOLOV7训练TT100K交通标识符数据集

《临江仙》 作者&#xff1a;缠中说禅 浊水倾波三万里&#xff0c;愀然独坐孤峰。龙潜狮睡候飙风。无情皆竖子&#xff0c;有泪亦英雄。 长剑倚天星斗烂&#xff0c;古今过眼成空。乾坤俯仰任穷通。半轮沧海上&#xff0c;一苇大江东。 一、yolov7环境搭建 参…

【内网穿透】远程访问RabbitMQ服务

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 转载自cpolar内网穿透的文章&#xff1a;无公网IP&…

【C语言】刷题训练营 —— 每日一练

文章目录 前言 BC113 小乐乐定闹钟BC114 小乐乐排电梯BC115 小乐乐与欧几里得BC116 小乐乐改数字BC107 矩阵转置BC117 小乐乐走台阶BC118 小乐乐与序列BC119 小乐乐与字符串BC121 小乐乐学编程BC122 小乐乐算平均分完结 前言 大家好&#xff0c;继续更新专栏 c_牛客&#xff0…

【C++】二叉搜索树Binary Search Tree

Binary Search Tree 二叉搜索树的概念二叉搜索树的操作二叉搜索树的实现查找插入删除 二叉搜索树的应用二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树又被称为二叉排序树&#xff0c;顾名思义&#xff0c;当我们使用中序遍历时&#xff0c;会得到一个有序的序列。二叉搜索…

进程信号的保存和处理

目录 &#x1f3c6;一、信号的保存 ①信号的捕捉 ②sigset_t ③sigaction &#x1f3c6;二、不可重入函数 &#x1f3c6;三、volatile &#x1f3c6;四、SIGCHLD &#x1f3c6;一、信号的保存 在聊信号保存之前&#xff0c;我们不妨想一个问题&#xff0c;如果把所有信号…

易岸教育:高端篇!公务员面试经验总结!

根据众多应聘者的面试经验&#xff0c;总结出以下几点供应聘者参考&#xff1a; 1、注意着装。 适当提高服装档次。 衣着得体大方&#xff0c;可以提升形象&#xff0c;增强自信。 2、安心。 要以一颗平常心正确对待面试&#xff0c;就要有受挫的心理准备。 即使面试失败了一…

【Python】学习导论:Python 简介

前言&#xff1a;XMind 脑图大纲 一、Python 的发展和演变 1.1 Python 1.0&#xff08;1994年&#xff09; 版本&#xff1a;Python 的第 1 个正式版本典型里程碑&#xff1a;包含了基本的语言特性和标准库 1.2 Python 2.0&#xff08;2000年&#xff09; 版本&#xff1a;Pyt…