JavaScript高级 —— 学习(一)

目录

一、作用域

(一)局部作用域

1.函数作用域

2.块作用域

(二)全局作用域

二、垃圾回收机制 GC

(一)生命周期

1.内存分配

2.内存使用

3.内存回收

4.特殊情况——内存泄漏:

注意:

(二)算法说明

1.堆栈空间分配区别

2.常见的浏览器垃圾回收算法

引用计数法(基本不咋用)

标记清除法

三、闭包

(一)闭包简介

(二)闭包的基本格式

(三)闭包应用——实现函数的私有

四、变量提升

五、函数进阶

(一)函数提升

(二)函数参数

1.动态参数

2.剩余参数

 展开运算符

求最大值

合并数组

(三)箭头函数

1.箭头函数介绍

2.基本语法

2.箭头函数参数

2.箭头函数 this

六、解构赋值

(一)数组解构

 特殊情况

1.变量多单元值少

2.变量少单元值多

3.利用剩余参数解决 2

 4.防止 undefined 传递

 5.按需导入忽略某些值

 6.支持多维数组的解构

(二)对象解构(特别重要)

1.对象解构语法

2.对象解构改名

3.简单数组对象解构

4.多级对象解构

遍历数组 forEach 方法 (重点)

筛选函数 filter 方法(重点)

练习: 对象解构在函数中的用处


一、作用域

(一)局部作用域

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

函数被执行时,优先查找当前函数作用域,如果找不到再层层往父亲层次查找,直到全局作用域

嵌套关系的作用域串联起来形成了作用域链

而且父亲不能访问孩子

1.函数作用域

函数内部声明的变量,外部无法访问,函数执行完毕内部的变量被清空了

2.块作用域

在 JavaScript 中被 { } 包围的代码被称为代码块,在代码块内部被声明的变量有可能无法被访问

用 let 和 const 声明会产生块作用域,外面无法访问

var 定义的变量不会产生块级作用域,外面可以访问

(二)全局作用域

<script> 标签 和 .js 文件的最外层,就是全局作用域,在其中声明的变量在其他作用域也可被访问

window 对象添加的属性默认也是全局的,不推荐

函数中没用关键字声明的 也默认为全局变量,不推荐

尽量少的减少全局变量,防止污染。

二、垃圾回收机制 GC

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

(一)生命周期

js 环境中分配的内存,一般的生命周期:

1.内存分配

声明变量函数对象时,系统自动分配内存

2.内存使用

读写内存,使用变量函数等

3.内存回收

使用完毕,由垃圾回收器自动回收不再使用的内存

4.特殊情况——内存泄漏:

程序中的内存由于某种原因未释放,或无法释放

注意:

全局变量一般不回收,关闭页面时回收

局部变量的值,不用了会被自动回收

(二)算法说明

1.堆栈空间分配区别

1、栈:操作系统自动分配释放函数的参数值,局部变量等,基本数据类型放到栈里面。

2、堆:由程序员分配释放,如果程序员不释放,就由垃圾回收机制回收,复杂数据类型放到堆里面。

2.常见的浏览器垃圾回收算法
引用计数法(基本不咋用)

定义内存不再使用的对象,看对象是否有指向它的引用,如果没有引用了就回收对象。

但是如果两个对象相会被引用 就无法回收了,因为一直使用这两个对象

算法:

记录被引用的次数

被引用就次数加 1 多次就累加

如果减少就减 1 --

引用次数为 0 就释放内存

标记清除法

定义无法到达的对象,从根部定期扫描对象,就是全局变量找不到的对象,就需要被回收。解决了上一个算法的问题

三、闭包

(一)闭包简介

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

内存函数加外层函数的变量就是闭包,就是里层函数使用外层函数的变量

<body>
  <script>
    function outer() {
      const a = 1
      function f() {
        console.log(a)
      }
      f()
    }
  </script>
</body>

(二)闭包的基本格式

外部的函数调用了函数内部的变量,最后本质是用 fun() 调用了 fn 函数

<body>
  <script>
    function outer() {
      const i = 1
      function fn() {
        console.log(i)
      }
     return fn
    }
    const fun =outer()
    fun()
  </script>
</body>

(三)闭包应用——实现函数的私有

比如统计函数被调用的次数,调用就次数加一

不能使用全局变量 容易被修改 所以可以用闭包进行封装

在外面改变 i 的值不会影响 结果的计算 因为 i 是局部作用域 在外面无法改变

而且 i 局部变量不会被回收 这是很巧妙的地方,外面定义了个全局作用域 result 一直在调用

count(),这样函数不结束被调用就不会被销毁,就能一直加加 i

这也属于内存泄露的一种情况

<body>
  <script>
    function count() {
      let i = 0
      function fn() {
        i++
        console.log(i)
      }
      return fn
    }
    const result = count()
  </script>
</body>

四、变量提升

es6 引入了块级作用域,let const 就更方便了

允许变量被声明前被访问 只有 var 变量存在

在代码执行前,会检测所有 var 变量 然后提到当前作用域的最前面进行定义

下面这段代码不会报错,按理来说会报错的,因为代码按顺寻执行,但是因为 var 变量 变量提升,所以定义了 var 类型的变量 num 但是赋值不会提升,所以输出 undefined

只提升声明 不提升赋值

<body>
  <script>
    console.log(num)
    var num = 10
  </script>
</body>

五、函数进阶

(一)函数提升

代码执行前也会 把所有函数声明提到当前作用域的最前面

<body>
  <script>
   fn()
   function fn(){
    console.log('函数提升')
   }
  </script>
</body>

 只提升函数声明不提升函数调用,调用还是按顺序执行的

下面这种情况会报错注意,因为下面 var 变量提升 但是只提升定义不提升赋值

就相当于

var fn

fn()

fn = function()

fn 被调用时不是个函数,所以会报错

<body>
  <script>
   fn()
   var fn = function (){
    console.log('函数提升')
   }
  </script>
</body>

(二)函数参数

1.动态参数

不知道实参的数量时 就可以用动态参数

arguments 函数内部内置的伪数组变量,包含了调用函数时传入的所有实参

只存在于函数内部,是动态的,实参有几个,伪数组里面就有几个

<body>
  <script>
   function getSum(){
    console.log(arguments)
   }
   getSum(2, 3, 1)
  </script>
</body>

 将 arguments 伪数组里面的元素求和

<body>
  <script>
    function getSum() {
      let sum = 0
      for (let i = 0; i < arguments.length; i++) {
        sum += arguments[i]
      }
      console.log(sum)
    }
    getSum(2, 3, 1)
  </script>
</body>
2.剩余参数

剩余参数也能完成上面的任务,不知道实参的数量,它是个真数组,可以用 push pop 方法

剩余参数允许我们将一个不定数量的参数表示为一个数组,它是把剩余的参数变成一个数组

用法差不多,实际开发中提倡使用 剩余参数

下面的例子中,先把 2 传到 参数 1 然后把 3 传给参数 b 最后把1, 5 ,9 单独封装成一个数

组,剩余参数的名字就是这么来的,就是被剩下的参数

<body>
  <script>
    function getSum(a, b, ...arr) {
      console.log(arr)
    }
    getSum(2, 3, 1, 5, 9)
  </script>
</body>
 展开运算符

... 三个点,如果不用在 函数参数中,就是起到展开数组的作用

最大的用处就是 求数组最大值,合并数组等

<body>
  <script>
    const arr = [1, 2, 3]
    console.log(...arr)
  </script>
</body>
求最大值

...能把数组变成字符串的形式

<body>
  <script>
    const arr = [1, 2, 3]
    console.log(Math.max(...arr))
  </script>
</body>
合并数组
<body>
  <script>
    const arr1 = [1, 2, 3]
    const arr2 = [2, 3, 4]
    const arr = [...arr1, ...arr2]
    console.log(arr)
  </script>
</body>

(三)箭头函数

1.箭头函数介绍

引入箭头函数的目的是让函数书写更简短,而且不绑定 this 箭头函数比函数表达式更简洁,

主要用于本来需要使用匿名函数的地方

2.基本语法

两种函数新旧对比,参数就正常写在小括号中

<body>
  <script>
    // 旧版函数写法
    const fn = function(){
      console.log(123)
    }
    // 新版箭头函数写法
    const fn1 = () => {
      console.log(123)
    }
  </script>
</body>

如果参数参数只有一个,小括号可以省略

<body>
  <script>
    const fn = x => {
      console.log(x)
    }
    fn(1)
  </script>
</body>

只有一行代码时可以省略大括号

<body>
  <script>
    const fn = x => console.log(x)
    fn(1)
  </script>
</body>

箭头函数能直接返回一个对象,因为后面大括号和对象的大括号冲突了,所以用小括号包住

<body>
  <script>
    const fn = (uname) => ({ uname: uname })
    fn('一个人')
  </script>
</body>
2.箭头函数参数

箭头函数没有 arguments 动态参数,但是有剩余参数 ...args

<body>
  <script>
    const getSum = (...arr) => {
      let sum = 0
      for (let i = 0; i < arr.length; i++) {
        sum += arr[i]
      }
      return sum
    }
    console.log(getSum(2, 3))
  </script>
</body>
2.箭头函数 this

函数外面的 this 指向 window 默认是 window

dom 回调函数中还是不推荐使用 箭头函数

this 之前的定义是 this 指向函数的调用者

这里的 this 指向对象 obj

<body>
  <script>
    const obj = {
      uname: '一个人',
      say: function () {
        console.log(this)
      }
    }
    obj.say()
  </script>
</body>

箭头函数的 this 指向箭头函数的上一级作用域链

下面代码都指向 window

<body>
  <script>
    const fn = () => {
      console.log(this)
    }
  </script>
</body>
​

<body>
  <script>
    const obj = {
      uname: '一个人',
      say: function () {
        console.log(this)
      }
    }
    obj.say()
  </script>
</body>

​

六、解构赋值

(一)数组解构

是将数组的单元值快速批量的赋值给一系列变量的简洁语法,就是把数组元素赋给变量,能分别得到三个变量

<body>
  <script>
    const arr = [100, 60, 80]
    const [max, min, avg] = arr
    console.log(max)
  </script>
</body>

 例子如下:数组解构时一定要在数组的前面加上分号,同理立即执行函数,要不然数组前面的数字就会连上数组 ,变成2 [b, a] = [a, b] 从而报错

<body>
  <script>
    let a = 1
    let b = 2;
    [b, a] = [a, b]
    console.log(a, b)  
  </script>
</body>
 特殊情况
1.变量多单元值少

如下代码,变量有a,b,c ,d 四个变量,但是只有1,2,3 三个单元值,abc 分别被赋值123,d的值为 undefined 很像前面的变量的赋值。

<body>
  <script>
   const [a,b,c,d] = [1,2,3]
  </script>
</body>
2.变量少单元值多

多余的单元值就不进行赋值了

3.利用剩余参数解决 2

利用 ... 展开运算符来存其余的数值

<body>
  <script>
   const [a,b,...c]= [1,2,3,4]
  </script>
</body>
 4.防止 undefined 传递

设置一个默认参数就能解决

<body>
  <script>
   const [a = 0,b = 0]= [1,2]
  </script>
</body>
 5.按需导入忽略某些值

如下面例子 就忽略了 后面的值 3

<body>
  <script>
   const [a,b, ,d]= [1,2,3,4]
  </script>
</body>
 6.支持多维数组的解构

下面成功帮助多维数组解构了

<body>
  <script>
   const [a, b, [c,d]] =  [1, 2, [3, 4]]
  </script>
</body>

(二)对象解构(特别重要)

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

1.对象解构语法

注意:必须等号左右两边的属性名和变量名必须相同,而且之前不能起和对象内部属性相同的变量名,要不然就会 undefined。

下面的例子和数组结构的方法类似

<body>
  <script>
    const { uname, age } = {
      uname: '一个人',
      age: 18
    }
    console.log(uname)
  </script>
</body>
2.对象解构改名

对象解构的变量名可以改名,但是语法很特殊,新改的名字写在后面。

<body>
  <script>
    const { uname: name, age } = {
      uname: '一个人',
      age: 18
    }
    console.log(name)
  </script>
</body>
3.简单数组对象解构
<body>
  <script>
   const arr = [{
    uname: '一个人',
    age: 18
   }]
   const [{uname, age}] = arr
   console.log(uname)
  </script>
</body>
4.多级对象解构

就如下形式书写即可,数组对象同理

<body>
  <script>
   const pig = {
    name: '佩奇',
    family:{
      mother: '猪妈妈',
      father: '猪爸爸',
      sister: '乔治'
    }
   }
   const {name, family:{mother, father,sister}} = pig
   console.log(mother)
  </script>
</body>

遍历数组 forEach 方法 (重点)

和 map 遍历类似 但是 map 最后返回一个数组 forEach 只进行遍历不返回数组,可以看作加强版的 for 循环

语法:被遍历的数组.forEach(function (当前数组元素,当前元素索引号)){

函数体

}

当前数组元素就是数组里面的值,会依次遍历输出出来,index 是每个元素的下标,下标可以省略

<body>
  <script>
    const arr = ['red', 'green', 'pink']
    const result = arr.forEach(function (item, index) {
      console.log(item)
      console.log(index)
    })
  </script>
</body>

筛选函数 filter 方法(重点)

filter() 方法是创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,用于筛选数组中符合条件的元素,并返回筛选后的数组。

<body>
  <script>
    const arr = [10, 20, 30]
    const newArr = arr.filter(item => item >= 20)
    console.log(newArr)
  </script>
</body>

练习: 对象解构在函数中的用处

结果展示:

 代码部分:
 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    const msg = {
      "code": 200,
      "msg": "获取新闻列表成功",
      "data": [
        {
          "id": 1,
          "title": "5G商用自己,三大运营商收入下降",
          "count": 58
        },
        {
          "id": 2,
          "title": "5G商用自己,三大运营商收入下降",
          "count": 56
        },
        {
          "id": 3,
          "title": "5G商用自己,三大运营商收入下降",
          "count": 1669
        }

      ]
    }
    function jie({ data: myData }) {
      console.log(myData)
    }
    jie(msg)
  </script>
</body>

</html>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【问题分析】InputDispatcher无焦点窗口ANR问题【Android 14】

1 问题描述 Monkey跑出的无焦点窗口的ANR问题。 特点&#xff1a; 1&#xff09;、上层WMS有焦点窗口&#xff0c;为Launcher。 2&#xff09;、native层InputDispacher无焦点窗口&#xff0c;上层为”recents_animation_input_consumer“请求了焦点&#xff0c;但是”rece…

亚信安慧AntDB引领优质解决方案

亚信安慧AntDB数据库在运营商自主可控替换项目中的成功应用&#xff0c;具有极其重要的意义。该数据库的落地&#xff0c;不仅为这一项目注入了强大的支持力量&#xff0c;还在更大程度上提升了整体的运营效能。作为一种高效可靠的数据库解决方案&#xff0c;AntDB引入了先进的…

C++从入门到精通——函数重载

函数重载 前言一、函数重载概念二、函数重载的分类参数类型不同的函数重载参数个数不同的函数重载参数类型顺序不同的函数重载 三、函数重载的具体代码展示main.cpp 四、为什么为什么C支持函数重载&#xff0c;而C语言不支持函数重载呢 前言 函数重载是指在同一个作用域内&…

vue实现文字一个字一个字的显示(开箱即用)

图示&#xff1a; 核心代码 Vue.prototype.$showHtml function (str, haveCallback null) {let timeFlag let abcStr for (let i 0; i < str.length; i) {(function (i) {timeFlag setTimeout(function () {abcStr str[i]haveCallback(abcStr)if ((i 1) str.length…

SI24R2E:智能电子学生卡2.4GHz考勤方案

今年年初教育部发布的《关于加强中小学生手机管理工作的通知》中提出&#xff0c;学生手机有限带入校园&#xff0c;原则上不得将个人手机带入校园&#xff0c;禁止带入课堂&#xff1b;应设立校内公共电话、建立班主任沟通热线、探索使用具备通话功能的电子学生证或提供其他家…

List操作add,clear,addall报错UnsupportedOperationException的解决办法

ArrayList和Arrays.ArrayList是两码事 ArrayList 支持 add&#xff0c;clear&#xff0c;addall Arrays.ArrayList不支持add&#xff0c;clear&#xff0c;addall 这个方法的使用时候&#xff0c;传递的数组必须是对象数组&#xff0c;而不是基本数据类型 JDK源码 /** *返回由…

LLM之RAG实战(三十六)| 使用LangChain实现多模态RAG

我们之前介绍的RAG&#xff0c;更多的是使用输入text来查询相关文档。在某些情况下&#xff0c;信息可以出现在图像或者表格中&#xff0c;然而&#xff0c;之前的RAG则无法检测到其中的内容。 针对上述情况&#xff0c;我们可以使用多模态大模型来解决&#xff0c;比如GPT-4-V…

【微服务】Sentinel(流量控制)

文章目录 1.基本介绍1.Sentinel是什么2.Sentinel主要特性3.Sentinel核心功能1.流量控制2.熔断降级3.消息削峰填谷 4.Sentinel两个组成部分 2.Sentinel控制台显示1.需求分析2.下载3.运行1.进入cmd2.输入java -jar sentinel-dashboard-1.8.0.jar3.查看默认端口8080 4.访问1.账号和…

数据结构课设-基于Python的校园导航系统(附源码)

一月份的数据结构课设完成后&#xff0c;我对Python的了解也更加深刻。现将课设报告及源码开源&#xff0c;不足之处希望大家指正。源码我放在博客主页的资源中&#xff0c;需要的话大家自行下载&#xff08;用户信息保存在 users.json 文件中&#xff0c;地图信息保存在 campu…

GooglePlay无法下载应用问题

问题如下 解决方法 1、实际上是因为google尚未添加apk downloader扩展程序 2、添加该扩展程序后&#xff0c;在应用中搜索应用名即可 欧克&#xff01;下载完成

IDEA设置内存大小不生效

IDEA设置内存大小不生效 100%可行的方法 -Xms512m -Xmx4096m1.首先要找对idea加载的是哪个配置文件。 2.找到idea启动文件夹&#xff0c;编辑idea.bat 添加打印修改文件路径的代码&#xff0c;运行idea.bat打印一下你的配置文件路径&#xff0c;找到路径 修改 然后运行idea.…

机器学习作业二之KNN算法

KNN&#xff08;K- Nearest Neighbor&#xff09;法即K最邻近法&#xff0c;最初由 Cover和Hart于1968年提出&#xff0c;是一个理论上比较成熟的方法&#xff0c;也是最简单的机器学习算法之一。该方法的思路非常简单直观&#xff1a;如果一个样本在特征空间中的K个最相似&…

vs2022 关于Python项目无法识别中文的解决方法

这是针对于vs2022安装和使用教程&#xff08;详细&#xff09;-CSDN博客 Python项目无法识别中文的解决方法的文章 一、问题 1.输入代码 print("你好Hello world&#xff01;") 2.启动&#xff0c;发现代码里有中文报错 二、解决方法 1.选择菜单栏里的工具->…

超实用的Maven指南

文章目录 实战记录&#x1f4dd;Maven 指令大全 &#x1f31f;找到没有被使用的jar&#xff08;analyze&#xff09;分析jar是被哪个maven引入&#xff08;tree&#xff09;&#x1f31f; dependencies&#xff08;Maven依赖&#xff09;build-resources&#xff08;资源导入&a…

如何提高知识库系统管理水平?

我们都有过这样的经历--遇到问题或紧急请求时&#xff0c;第一时间就是向知识库系统寻求帮助。很多时候&#xff0c;当你翻遍了无穷无尽的文档&#xff0c;却发现没有任何东西能够摆脱此时的困境&#xff0c;这时&#xff0c;向服务台提交工单成了不可避免的解决方式&#xff0…

基于Java的新生入学报到管理系统的设计与实现(论文+源码+PPT)_kaic

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息…

2024年2月游戏手柄线上电商(京东天猫淘宝)综合热销排行榜

鲸参谋监测的线上电商&#xff08;京东天猫淘宝&#xff09;游戏手柄品牌销售数据已出炉&#xff01;2月游戏手柄销售数据呈现出强劲的增长势头。 根据鲸参谋数据显示&#xff0c;今年2月游戏手柄月销售量累计约43万件&#xff0c;同比去年上涨了78%&#xff1b;销售额累计达1…

Stable Diffusion 模型分享:SDXL Unstable Diffusers ☛ YamerMIX(混合风格)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八下载地址模型介绍

每日一题 --- 快乐数[力扣][Go]

快乐数 题目&#xff1a;202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到…

Spring用到了哪些设计模式?

目录 Spring 框架中⽤到了哪些设计模式&#xff1f;工厂模式单例模式1.饿汉式&#xff0c;线程安全2.懒汉式&#xff0c;线程不安全3.懒汉式&#xff0c;线程安全4.双重检查锁&#xff08;DCL&#xff0c; 即 double-checked locking&#xff09;5.静态内部类6.枚举单例 代理模…