【JavaScript】08-作用域+箭头函数+解构赋值

本文以后的文章主要是介绍ES6+语法

目录

1.作用域

1.1 局部作用域

1.1.1 函数作用域

1.1.2 块作用域

1.2 全局作用域

1.3 作用域链

1.4 垃圾回收机制GC

1.4.1 内存生命周期

1.4.2 注意

1.4.3 内存泄漏

1.5 闭包

1.5.1 概念

1.5.2 闭包的作用

1.5.3 闭包应用

1.6 变量提升

2. 函数进阶

2.1 函数提升

2.2 函数参数

2.2.1 动态参数

2.2.2 剩余参数

2.2.3 补充展开运算符

2.3 箭头函数(重要)

2.3.1 各种语法

2.3.2 对象的箭头函数语法

2.3.3 箭头函数的参数

2.3.4 箭头函数的 this

3. 解构赋值

3.1 数组解构

3.1.1 基本语法

3.1.2 交换变量

3.1.3 必须要加分号情况

3.1.4 单元值数量与变量数量不匹配

① 单元值少 变量多

② 变量少 单元值多

③ 防止undefined传递

④ 按需导入

3.1.5 多维数组解构

3.2 对象解构

3.2.1 基本语法

3.2.2 数组对象的解构

3.2.3 多级对象解构

① 对象对象嵌套

② 数组对象嵌套

③ 操作案例(后更)

3.2.4 遍历数组forEach

3.3 渲染商品案例(后更)


1.作用域

规定了变量能够被访问的范围

1.1 局部作用域

1.1.1 函数作用域

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

函数的参数也是函数内部的局部变量。

不同函数内部声明的变量无法互相访问。

函数执行完毕后,函数内部的变量实际被清空了。

1.1.2 块作用域

在JS中使用 { } 包裹的代码块内声明的变量外部将(有可能)无法被访问。

注意:

1. let 声明的变量会产生块作用域,var不会有块作用域

2. const 声明的会产生块作用域

3. 不同代码块之间的函数无法互相使用

    <script>function fn(){//块作用域}// for(let i=0; i<3; i++){ //     //块作用域//     console.log(i);// }// console.log(i); // 报错for(var i=0; i<3; i++){ //块作用域console.log(i);}console.log(i);  // 3// var没有块作用域</script>

1.2 全局作用域

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

注意:

1. 为window对象动态添加的属性默认也是全局的,不推荐!

2. 函数中未使用任何关键字声明的变量为全局变量,不推荐!

3. 尽可能少的使用全局变量,防止全局变量被污染。


1.3 作用域链

例如:

a最终的输出结果是多少?

就近原则

输出 a = 2

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

在函数被执行时优先查找当前函数的作用域,如果当前作用域查找不到则会依次逐级查找父级作用域 (类型冒泡),直到全局作用域。

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

但是父级作用域 无法 向下查找子作用域。


1.4 垃圾回收机制GC

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

1.4.1 内存生命周期

1. 内存分配

当我们声明变量、函数、对象的时候,系统会自动为他们分配内存

2. 内存使用

即读写内存:使用变量函数等

3. 内存回收

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

1.4.2 注意

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

2. 一般情况下的局部变量的值不用了就会被自动回收

1.4.3 内存泄漏

程序中分配的内存由于某种原因未释放无法释放的内存泄漏

这里就不再介绍回收的算法了,可自行了解。


1.5 闭包

1.5.1 概念

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

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

且内层函数用到了外层的变量

function outer() {let a = 1;function f() {console.log(a);}f();
}
outer();

如上述的举例

f() 用到了外层的变量

const a和 f() 加在一起 称为闭包


1.5.2 闭包的作用

封闭数据,提供操作,外部也可以访问函数内部的变量

基本格式

        // 常见闭包 外部可以访问函数内部变量function outer(){let a = 10;function fn(){console.log(a);}// fn();return fn;  // outer是接收者}// outer()  ----  fn  ---- function fn() {}// const fun = outer()// const fun = function fn() {}const fun = outer();fun(); // 外部函数访问函数内部变量

1.5.3 闭包应用

实现数据的私有

比如,我们要做个统计函数调用次数,函数调用一次就++

    <script>// 统计函数调用次数// 普通形式let i = 0;function fn(){i++;console.log(`函数被调用了${i}次`);  // 风险:i是全局变量 容易被修改}</script>

        // 闭包形式 实现数据私有// 这里的i不会被垃圾回收 因为被反复调用 产生内存泄漏function count(){let i = 0;function fn(){i++;console.log(`函数被调用了${i}次`);}return fn;}const fun = count();


1.6 变量提升

JS的缺陷 与var有关

在作用域执行之前,所有var声明的变量提升到当前作用域的最前面。

但是,只提升的是“声明”,不提升“赋值”

let const 没有变量提升

    <script>// 所有var声明的变量提升到 当前作用域 的最前面// 只提升的是“声明”,不提升“赋值”// 相当于只提升了 num// var num console.log(num + '件');  //undefined件var num = 10;</script>

2. 函数进阶

2.1 函数提升

示例:

    <script>fn();  // 可以输出 成功提升// 会把函数声明提升到当前作用域的最前面// 只提升函数声明 不提示函数调用function fn(){console.log('函数提升');  }</script>

但是有一种情况不能:

        // 函数表达式fun();  // 报错// 只提升声明// 不提升赋值 这里相当于对fun赋值var fun = function(){console.log('函数表达式');}// 函数表达式必须先声明和赋值 后调用

2.2 函数参数

2.2.1 动态参数

例如 产品需求:写一个求和函数

不管传来几个参数,都要把和求出来

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

    <script>function getSum(){// 动态参数 arguments没有形参 只存在于函数里面console.log(arguments);// 是个伪数组let sum = 0;for(let i=0; i<arguments.length; i++){sum += arguments[i];}console.log(sum);}getSum(2,3);</script>

2.2.2 剩余参数

允许将一个不定数量的变量传入函数并存入数组

    <script>// ... 剩余参数// 要求至少传来X个参数时使用// 例如至少传来两个 剩下的存入arr数组// 剩余参数灵活 且 是真数组 可以使用数组的方法pop push等等function getSum(a,b,...arr){// arr 或 其他随便写 可以得到 传来的参数 [2,3]console.log(arr);}getSum(2,3);  // 空数组getSum(1,2,3,4);   // [3,4]</script>

2.2.3 补充展开运算符

展开运算符(...)能将一个数组进行展开

注意:不会修改原数组

应用:求数组最值、合并数组等

    <script>const arr = [1,2,3];// console.log(...arr); // 展开数组// 求最值console.log(Math.max(...arr))  // 3console.log(Math.min(...arr)); // 1// 合并数组const arr2 = [3,4,5];// 合并arr arr2const arr1 = [...arr,...arr2];console.log(arr1);</script>

2.3 箭头函数(重要)

要求能写出箭头函数的不同写法

引入箭头函数的目的是为了写更简短的代码并且不用绑定 this,箭头函数的语法比函数表达式更简洁。

箭头函数更适用于那些本来需要匿名函数的地方。

2.3.1 各种语法

    <script>// function fn() {//     console.log(123);// }// 箭头函数写法// 主要是函数表达式形式// () 代表参数  => 代表functionconst fn = () => {console.log(123);}fn();// 带参数const fn1 = (x) => {console.log(x);}fn1(1);// 如果只有一个参数 小括号可以省略const fn2 = x => {console.log(x);}fn2(2);// 只有一行代码 可以省略大括号const fn3 = x => console.log(x);fn3(3);// 只有一行时需要返回值时 可以省略 {} 和 returnconst fn4 = x => x + x;console.log(fn4(4));</script>

比如,阻止表单的默认提交

const form = document.querySelector('form')
form.addEventListener('click', ev => ev.preventDefault());

2.3.2 对象的箭头函数语法

        // 箭头函数可以直接返回一个对象 需要()包着const fn5 = (uname) => ({uname:uname})  // 实参传给形参 第一个uname是属性名 uname是属性值console.log(fn5('刘德华'));

2.3.3 箭头函数的参数

普通函数有 arguments 动态函数

箭头函数没有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);console.log(result);</script>

2.3.4 箭头函数的 this

箭头函数之前的普通函数是根据它是被如何调用的来定义这个函数的this值,很麻烦。

    <script>console.log(this);  // window// 普通函数function fn(){console.log(this);  // window 指向的是函数的调用者}fn();  // window.fn();// 声明一个对象// 对象方法里的thisconst obj = {name: 'zzz',sayHi: function(){console.log(this);  // obj调用sayHi  // 指向的是obj}}obj.sayHi();</script>

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

        // 箭头函数的thisconst fn1 = () => {console.log(this);  // window 是这个作用域的上一级// 箭头函数本身没有this 只能指向上一层作用域的this}fn1();  // 对象方法的箭头函数的 thisconst obj1 = {uname : 'bbb',ff: () =>{console.log(this);  // window // 本作用域ff没有this 上一层obj1的作用域是window// 因为调用obj1的是window 指向的是调用上一级的 即window}}obj1.ff();// 普通与箭头嵌套的函数const obj2 = {uname: 'nnn',bb:function(){console.log(this);  // 普通函数obj2let i = 10;// 普通函数里再写一个箭头函数const count = ()=>{console.log(this);}count();  // 指向obj2}}obj2.bb();

注意:

在DOM事件的回调函数不太推荐箭头函数


3. 解构赋值

需要知道解构的语法与分类,使用解构简洁语法快速变量赋值

3.1 数组解构

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

3.1.1 基本语法

1. = 左侧的 [ ] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量

2. 变量的顺序对应数组单元值的位置依次进行赋值操作

    <script>const arr = [100,60,80];// 数组解构 批量复制const [max,min,avg] = arr;// max = arr[0]  min = arr[1]  avg = arr[2]console.log(max);console.log(min);console.log(avg);</script>

将最大值和最小值函数返回值 解构为 max min

    <script>function getValue(){return [60,80];}const [min,max] = getValue();console.log(min,max);</script>

3.1.2 交换变量

        // 交换变量let a = 1;let b = 2;  // 这里必须加分号[b,a] = [a,b];console.log(a,b);   // 2,1

3.1.3 必须要加分号情况

js前面加分号

1. 立即执行函数

( function t() { })();
// 或者
;( function t() { })()

2. 数组解构

;[b,a] = [a,b]
    <script>// const arr = [1,2,3];const str = 'zzz';// map遍历 // 前面必须有分号[1,2,3].map(function(item){console.log(item);})</script>

3.1.4 单元值数量与变量数量不匹配

① 单元值少 变量多
        // 单元值少,变量多const [a,b,c,d] = [1,2,3];console.log(a);console.log(b);console.log(c);console.log(d);  // undefined
② 变量少 单元值多
        // 单元值多,变量少const [x,y] = [1,2,3];console.log(x); //1console.log(y); //2

可以用剩余参数解决:

        // 单元值多,变量少  剩余参数解决const [x,y,...m] = [1,2,3];console.log(x); //1console.log(y); //2console.log(m); //真数组  [3]
③ 防止undefined传递

给一个初始默认值即可

        // 单元值少,变量多 给定所有的变量 初始默认值const [a=0,b=0,c=0,d=0] = [1,2,3];console.log(a);console.log(b);console.log(c);console.log(d);  // 0
④ 按需导入

按需导入 忽略某些返回值的传入

        // 按需导入const [a=0,,c=0] = [1,2,3];console.log(a);  // 1console.log(c);  // 3

3.1.5 多维数组解构

        // 多维数组解构// 普通const arr = [1,2,[3,4]];console.log(arr[0]);console.log(arr[1]);console.log(arr[2]); // [3,4]console.log(arr[2][0]);  // 3  // 解构const [a,b,[c,d]] = [1,2,[3,4]];console.log(a);  //1console.log(b);  //2console.log(c);  //3console.log(d);

3.2 对象解构

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

3.2.1 基本语法

1. = 左侧的{ } 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量

2. 对象属性的值将被赋值给与属性名相同的变量

3. 注意解构的变量名不要和外面的变量名冲突,否则报错

4. 对象中找不到与变量名一致的属性时变量值为undefined

    <script>const obj = {uname: 'zzz',age:18}// 一般 obj.uname  obj.ageconst {uname,age} = obj// 变量名 和 属性名 必须相同// 但是外面不能有 uname 和 age一样的变量名// 等同于 const uname = obj.unameconsole.log(uname);console.log(age);</script>

但是当外面有和属性名一样的变量名时

    <script>const uname = 'bbb';const obj = {uname: 'zzz',age:18}// 外面的变量名和属性名一样// 旧名: 新名const {uname:username,age} = obj;console.log(username);</script>

3.2.2 数组对象的解构

const pig = [{uname:'佩奇',age:6}
]
        // 解构数组对象const pig = [{uname: '佩奇',age: 6}]// [{ }]const [{uname,age}] = pig;console.log(uname);console.log(age);

3.2.3 多级对象解构

① 对象对象嵌套
        // 多级对象解构// 对象对象时const pig = {name:'佩奇',family:{mother:'猪妈妈',father:'猪爸爸',brother:'乔治'},age:6}// 多级嵌套时 用 : 打开内部的对象const {name,family:{mother,father,brother},age} = pig;console.log(name);console.log(mother);console.log(father);console.log(brother);console.log(age);
② 数组对象嵌套
        // 多级对象解构// 数组对象const person = [{name:'佩奇',family:{mother:'猪妈妈',father:'猪爸爸',brother:'乔治'},age:6}]const [{name,family:{mother,father,brother},age}] = person;console.log(name);console.log(mother);console.log(father);console.log(brother);console.log(age);
③ 操作案例(后更)

后更


3.2.4 遍历数组forEach

forEach调用数组的每个元素,并将元素传递给回调函数

不会返回数组,只遍历值。

与map的区别在于是否能返回数组

它适合遍历数组对象

语法

被遍历的数组.forEach(function (当前数组元素,当前元素索引号){// 函数体// 当前数组元素必须写 索引号可以不写
})
    <script>const arr = ['red','green','pink'];// function()回调函数arr.forEach(function(item,index){console.log(item);  // red green pinkconsole.log(index);  // 0 1 2})</script>

3.3 渲染商品案例(后更)

后更


本文主要介绍ES6中的作用域+箭头函数+解构赋值的相关知识点,相关综合案例后续编辑。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql中的常用函数

1、datediff(date1,date2) date1减去date2&#xff0c;返回两个日期之间的天数。 SELECT DATEDIFF(2008-11-30,2008-11-29) AS DiffDate -- 返回1 SELECT DATEDIFF(2008-11-29,2008-11-30) AS DiffDate -- 返回-1 2、char_length(s) 返回字符串 s 的字符数 3、round(x,d)…

百度移动生态事业群聚焦UGC战略,贴吧迎新调整

易采游戏网3月8日独家消息&#xff1a;近日据内部消息人士透露&#xff0c;百度移动生态事业群正积极将用户生成内容&#xff08;UGC&#xff09;作为新的战略重点。此举标志着百度对UGC价值的重视与重塑&#xff0c;同时也预示着其旗下重要平台——百度贴吧将迎来一轮重大的调…

开源项目介绍:Native-LLM-for-Android

项目地址&#xff1a;Native-LLM-for-Android 创作活动时间&#xff1a;2025年 支持在 Android 设备上运行大型语言模型 &#xff08;LLM&#xff09; &#xff0c;具体支持的模型包括&#xff1a; DeepSeek-R1-Distill-Qwen: 1.5B Qwen2.5-Instruct: 0.5B, 1.5B Qwen2/2.5VL:…

STM32标准库代码详解之GPIO

GPIO的初始化代码如下&#xff1a; /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟&#xff0c;使用外设必须开启/*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 GPIO_InitStructure.GPIO_Mode GPIO_Mo…

实现Django和Transformers 构建智能客服大模型(模拟订单系统)

一、环境安装准备 #git拉取 bert-base-chinese 文件#创建 虚拟运行环境python -m venv myicrplatenv#刷新source myicrplatenv/bin/activate#python Django 集成nacospip install nacos-sdk-python#安装 Djangopip3 install Django5.1#安装 pymysql settings.py 里面需要 # 强制…

Apache Kafka单节点极速部署指南:10分钟搭建开发单节点环境

Apache Kafka单节点极速部署指南&#xff1a;10分钟搭建开发单节点环境 Kafka简介&#xff1a; Apache Kafka是由LinkedIn开发并捐赠给Apache基金会的分布式流处理平台&#xff0c;现已成为实时数据管道和流应用领域的行业标准。它基于高吞吐、低延迟的设计理念&#xff0c;能够…

浅论数据库聚合:合理使用LambdaQueryWrapper和XML

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、数据库聚合替代内存计算&#xff08;关键优化&#xff09;二、批量处理优化四、区域特殊处理解耦五、防御性编程增强 前言 技术认知点&#xff1a;使用 XM…

【C++设计模式】第四篇:建造者模式(Builder)

注意&#xff1a;复现代码时&#xff0c;确保 VS2022 使用 C17/20 标准以支持现代特性。 分步骤构造复杂对象&#xff0c;实现灵活装配 1. 模式定义与用途 核心目标&#xff1a;将复杂对象的构建过程分离&#xff0c;使得同样的构建步骤可以创建不同的表示形式。 常见场景&am…

uploadlabs经验总结

目录 一、基础上传漏洞&#xff08;太过简单目前环境不可能存在&#xff09; 1、抓包然后改后缀进行绕过 2、抓包然后改上传文件类型进行绕过 3、改后缀大小写绕过&#xff0c;以及收尾加空格&#xff0c;加::$DATA,加点等等 4、黑名单不完整绕过&#xff0c;复习后缀绕过&…

若依ry-vue分离板(完整版)前后端部署

目录 1.目标 2.准备工作 3.源码下载 4.整理前后端目录 5.先部署后端 &#xff08;1&#xff09;导入数据库 &#xff08;2&#xff09;改代码数据库配置 &#xff08;3&#xff09;运行redis &#xff08;4&#xff09;运行执行文件 &#xff08;5&#xff09;后端启…

重构谷粒商城09:人人开源框架的快速入门

谷粒商城09——人人开源框架的快速入门 前言&#xff1a;这个系列将使用最前沿的cursor作为辅助编程工具&#xff0c;来快速开发一些基础的编程项目。目的是为了在真实项目中&#xff0c;帮助初级程序员快速进阶&#xff0c;以最快的速度&#xff0c;效率&#xff0c;快速进阶…

Linux | Vim 鼠标不能右键粘贴、跨系统复制粘贴

注&#xff1a;本文为 “ Vim 中鼠标右键粘贴、跨系统复制粘贴问题解决方案” 相关文章合辑。 未整理去重。 Linux 入门&#xff1a;vim 鼠标不能右键粘贴、跨系统复制粘贴 foryouslgme 发布时间 2016 - 09 - 28 10:24:16 Vim基础 命令模式(command-mode)插入模式(insert-m…

【JavaWeb】Web基础概念

文章目录 1、服务器与客户端2、服务器端应用程序3、请求和响应4、项目的逻辑构成5、架构5.1 概念5.2 发展演变历程单一架构分布式架构 5.3 单一架构技术体系 6、本阶段技术体系 1、服务器与客户端 ①线下的服务器与客户端 ②线上的服务器与客户端 2、服务器端应用程序 我…

基于云的内容中台核心优势是什么?

弹性云架构赋能资源整合 现代企业通过弹性云架构实现多源数据资源的深度整合&#xff0c;其动态扩展能力可自动适配业务流量波动。基于分布式存储与容器化部署&#xff0c;系统能够无缝对接CRM、ERP等企业软件集成&#xff0c;实现跨平台数据实时同步。值得注意的是&#xff0…

数据库基础练习1

目录 1.创建数据库和表 2.插入数据 创建一个数据库&#xff0c;在数据库种创建一张叫heros的表&#xff0c;在表中插入几个四大名著的角色&#xff1a; 1.创建数据库和表 #创建表 CREATE DATABASE db_test;#查看创建的数据库 show databases; #使用db_test数据库 USE db_te…

亲测解决笔记本触摸板使用不了Touchpad not working

这个问题可以通过FnFxx来解决&#xff0c;笔记本键盘上Fxx会有一个触摸板图标。如果不行应该玉藻设置中关了&#xff0c;打开即可。 解决办法 在蓝牙&#xff0c;触摸板里打开即可。 Turn it on in settings。

Vue23Web 基礎性拉滿的面試題(2025版)還沒更新完...

Vue2&3 基礎性1. 關於Vue2和Vue3生命週期的差別2. Vue2&3組件之間傳參不同點Vue2 傳遞與接收Vue3 傳遞與接收 (使用script setup語法糖)Vue3 傳遞與接收 (不使用script setup語法糖) 3. Vue2&3 keep-alive 組件Vue2 keep-aliveVue3 keep-alive 進階性爲什麽POST請求…

动态ip和静态ip适用于哪个场景?有何区别

在数字化浪潮席卷全球的今天&#xff0c;IP地址作为网络世界的“门牌号”&#xff0c;其重要性不言而喻。然而&#xff0c;面对动态IP与静态IP这两种截然不同的IP分配方式&#xff0c;许多用户往往感到困惑&#xff1a;它们究竟有何区别&#xff1f;又分别适用于哪些场景呢&…

深度学习模型Transformer核心组件—自注意力机制

第一章&#xff1a;人工智能之不同数据类型及其特点梳理 第二章&#xff1a;自然语言处理(NLP)&#xff1a;文本向量化从文字到数字的原理 第三章&#xff1a;循环神经网络RNN&#xff1a;理解 RNN的工作机制与应用场景(附代码) 第四章&#xff1a;循环神经网络RNN、LSTM以及GR…

FreeRTOS 源码结构解析与 STM32 HAL 库移植实践(任务创建、删除篇)

1. FreeRTOS源码结构介绍 1.1 下载源码 ​ 点击官网地址&#xff0c;选择 FreeRTOS 202212.01非 LTS 版本&#xff08;非长期支持版&#xff09;&#xff0c;因为这个版本有着最全的历程和更多型号处理器支持。 1.2 文件夹结构介绍 ​ 下载后主文件 FreeRTOSv202212.01 下包…