JavaScript 进阶 - 第1天

文章目录

  • 前言
  • 一、作用域
    • 1. 局部作用域
      • 1.1 函数作用域
      • 1.2 块作用域
    • 2. 全局作用域
    • 3. 作用域链
    • 4. 闭包
    • 5. 变量提升
  • 二、函数
    • 1. 函数提升
    • 2. 函数参数
      • 2.1 默认值
      • 2.2 动态参数
      • 2.3 剩余参数
    • 3. 箭头函数
  • 三、解构赋值
    • 1. 数组解构
    • 2. 对象解构
  • 四、综合案例
    • 1. forEach遍历数组
    • 2. filter筛选数组


前言

学习作用域、变量提升、闭包等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法,降低代码的冗余度。

  • 理解作用域对程序执行的影响
  • 能够分析程序执行的作用域范围
  • 理解闭包本质,利用闭包创建隔离作用域
  • 了解什么变量提升及函数提升
  • 掌握箭头函数、解析剩余参数等简洁语法

一、作用域

了解作用域对程序执行的影响及作用域链的查找机制,使用闭包函数创建隔离作用域避免全局变量污染。

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

1. 局部作用域

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

1.1 函数作用域

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

<script>// 声明 counter 函数function counter(x, y) {// 函数内部声明的变量const s = x + yconsole.log(s) // 18}// 设用 counter 函数counter(10, 8)// 访问变量 sconsole.log(s)// 报错
</script>

总结:

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

1.2 块作用域

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

<script>{// age 只能在该代码块中被访问let age = 18;console.log(age); // 正常}// 超出了 age 的作用域console.log(age) // 报错let flag = true;if(flag) {// str 只能在该代码块中被访问let str = 'hello world!'console.log(str); // 正常}// 超出了 age 的作用域console.log(str); // 报错for(let t = 1; t <= 6; t++) {// t 只能在该代码块中被访问console.log(t); // 正常}// 超出了 t 的作用域console.log(t); // 报错
</script>

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

<script>// 必须要有值const version = '1.0.0';// 不能重新赋值// version = '1.0.1';// 常量值为对象类型const user = {name: '小明',age: 18}// 不能重新赋值user = {};// 属性和方法允许被修改user.name = '小小明';user.gender = '男';
</script>

总结:

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

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

2. 全局作用域

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

全局作用域中声明的变量,任何其它作用域都可以被访问,如下代码所示:

<script>// 全局变量 nameconst name = '小明'// 函数作用域中访问全局function sayHi() {// 此处为局部console.log('你好' + name)}// 全局变量 flag 和 xconst flag = truelet x = 10// 块作用域中访问全局if(flag) {let y = 5console.log(x + y) // x 是全局的}
</script>

总结:

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

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

3. 作用域链

<script>// 全局作用域let a = 1let b = 2// 局部作用域function f() {let c// 局部作用域function g() {let d = 'yo'}}
</script>

函数内部允许创建新的函数,f 函数内部创建的新函数 g,会产生新的函数作用域,由此可知作用域产生了嵌套的关系。

父子关系的作用域关联在一起形成了链状的结构,作用域链的名字也由此而来。

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

<script>// 全局作用域let a = 1let b = 2// 局部作用域function f() {let c// let a = 10;console.log(a) // 1 或 10console.log(d) // 报错// 局部作用域function g() {let d = 'yo'// let b = 20;console.log(b) // 2 或 20}// 调用 g 函数g()}console.log(c) // 报错console.log(d) // 报错f();
</script>

总结:

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

4. 闭包

1.怎么理解闭包?

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

2.闭包的作用?

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

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

  • 内存泄漏

5. 变量提升

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

<script>// 访问变量 strconsole.log(str + 'world!');// 声明变量 strvar str = 'hello ';
</script>

总结:

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

二、函数

知道函数参数默认值、动态参数、剩余参数的使用细节,提升函数应用的灵活度,知道箭头函数的语法及与普通函数的差异。

1. 函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用。

<script>// 调用函数foo()// 声明函数function foo() {console.log('声明之前即被调用...')}// 不存在提升现象bar()  // 错误var bar = function () {console.log('函数表达式不存在提升现象...')}
</script>

总结:

  1. 函数提升能够使函数的声明调用更灵活
  2. 函数表达式不存在提升的现象
  3. 函数提升出现在相同作用域当中

2. 函数参数

函数参数的使用细节,能够提升函数应用的灵活度。

2.1 默认值

<script>// 设置参数默认值function sayHi(name="小明", age=18) {document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);}// 调用函数sayHi();sayHi('小红');sayHi('小刚', 21);
</script>

总结:

  1. 声明函数时为形参赋值即为参数的默认值
  2. 如果参数未自定义默认值时,参数的默认值为 undefined
  3. 调用函数时没有传入对应实参时,参数的默认值被当做实参传入

2.2 动态参数

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

<script>// 求生函数,计算所有参数的和function sum() {// console.log(arguments)let s = 0for(let i = 0; i < arguments.length; i++) {s += arguments[i]}console.log(s)}// 调用求和函数sum(5, 10)// 两个参数sum(1, 2, 4) // 两个参数
</script>

总结:

  1. arguments 是一个伪数组
  2. arguments 的作用是动态获取函数的实参

2.3 剩余参数

<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. ... 是语法符号,置于最末函数形参之前,用于获取多余的实参
  2. 借助 ... 获取的剩余实参,是个真数组

3. 箭头函数

箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。

<script>// const fn = function () {//   console.log(123)// }// 1. 箭头函数 基本语法// const fn = () => {//   console.log(123)// }// fn()// const fn = (x) => {//   console.log(x)// }// fn(1)// 2. 只有一个形参的时候,可以省略小括号// const fn = x => {//   console.log(x)// }// fn(1)// // 3. 只有一行代码的时候,我们可以省略大括号// const fn = x => console.log(x)// fn(1)// 4. 只有一行代码的时候,可以省略return// const fn = x => x + x// console.log(fn(1))// 5. 箭头函数可以直接返回一个对象// const fn = (uname) => ({ uname: uname })// console.log(fn('刘德华'))</script>

总结:

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

箭头函数中没有 arguments,只能使用 ... 动态获取实参

  <script>// 1. 利用箭头函数来求和const getSum = (...arr) => {let sum = 0for (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。

 <script>// 以前this的指向:  谁调用的这个函数,this 就指向谁// console.log(this)  // window// // 普通函数// function fn() {//   console.log(this)  // window// }// window.fn()// // 对象方法里面的this// const obj = {//   name: 'andy',//   sayHi: function () {//     console.log(this)  // obj//   }// }// obj.sayHi()// 2. 箭头函数的this  是上一层作用域的this 指向// const fn = () => {//   console.log(this)  // window// }// fn()// 对象方法箭头函数 this// const obj = {//   uname: 'pink老师',//   sayHi: () => {//     console.log(this)  // this 指向谁? window//   }// }// obj.sayHi()const obj = {uname: 'pink老师',sayHi: function () {console.log(this)  // objlet i = 10const count = () => {console.log(this)  // obj }count()}}obj.sayHi()</script>

三、解构赋值

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

1. 数组解构

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法,如下代码所示:

<script>// 普通的数组let arr = [1, 2, 3]// 批量声明变量 a b c // 同时将数组单元值 1 2 3 依次赋值给变量 a b clet [a, b, c] = arrconsole.log(a); // 1console.log(b); // 2console.log(c); // 3
</script>

总结:

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

2. 对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法,如下代码所示:

<script>// 普通对象const user = {name: '小明',age: 18};// 批量声明变量 name age// 同时将数组单元值 小明  18 依次赋值给变量 name  ageconst {name, age} = userconsole.log(name) // 小明console.log(age) // 18
</script>

总结:

  1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
  2. 对象属性的值将被赋值给与属性名相同的变量
  3. 对象中找不到与变量名一致的属性时变量值为 undefined
  4. 允许初始化变量的默认值,属性不存在或单元值为 undefined 时默认值才会生效

注:支持多维解构赋值

<body><script>// 1. 这是后台传递过来的数据const msg = {"code": 200,"msg": "获取新闻列表成功","data": [{"id": 1,"title": "5G商用自己,三大运用商收入下降","count": 58},{"id": 2,"title": "国际媒体头条速览","count": 56},{"id": 3,"title": "乌克兰和俄罗斯持续冲突","count": 1669},]}// 需求1: 请将以上msg对象  采用对象解构的方式 只选出  data 方面后面使用渲染页面// const { data } = msg// console.log(data)// 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数// const { data } = msg// msg 虽然很多属性,但是我们利用解构只要 data值function render({ data }) {// const { data } = arr// 我们只要 data 数据// 内部处理console.log(data)}render(msg)// 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myDatafunction render({ data: myData }) {// 要求将 获取过来的 data数据 更名为 myData// 内部处理console.log(myData)}render(msg)</script>

四、综合案例

1. forEach遍历数组

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

注意:

1.forEach 主要是遍历数组

2.参数当前数组元素是必须要写的, 索引号可选。

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

2. 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>

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

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

相关文章

Capto2024软件怎么下载安装? 【详细安装图文教程】

Capto 2024是一款专为Mac用户设计的屏幕录制编辑软件。无论是想要制作教育视频、工作演示、游戏录制&#xff0c;还是进行简单的屏幕捕捉&#xff0c;Capto 2024都能满足您的需求。接下来&#xff0c;我将详细介绍其主要功能、特点以及使用场景&#xff0c;并为您评价这款软件。…

安装multisim14.0

前言 文件准备 软件安装 1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 12、 13、 14、汉化 15、在软件安装路径下打开”stringfiles“文件夹&#xff0c; Circuit Design Suite 14.0\stringfiles 16、 17、 18、 19、 20、运行multisim14.0

try-with-resources 工作原理

概述 try-with-resources 是 Java 7 引入的一种语法糖&#xff0c;用于简化资源管理&#xff0c;确保在使用资源后自动关闭它们。它是 try 语句的增强形式&#xff0c;可以在资源使用完毕后自动调用它们的 close() 方法&#xff0c;从而避免资源泄漏。 但这有个前提&#xff1…

Java多线程面试重点-2

16.Synchronized关键字加在静态方法和实例方法的区别? 修饰静态方法&#xff0c;是对类进行加锁&#xff08;Class对象&#xff09;&#xff0c;如果该类中有methodA和methodB都是被Synch修饰的静态方法&#xff0c;此时有两个线程T1、T2分别调用methodA()和methodB()&#x…

对于千兆变压器(Gigabit Transformer)的设计

对于千兆变压器&#xff08;Gigabit Transformer&#xff09;的设计&#xff0c;以下是一些关键方面的详细说明&#xff1a; 1. **频率特性&#xff1a;** 千兆变压器需要能够在高频率下工作&#xff0c;通常在1 GHz以上。为了确保良好的性能&#xff0c;设计中需要选择合适的…

热门开源项目推荐:智谱GLM-4-9B和ChatGLM3-6B

目录 热门开源项目推荐&#xff1a;智谱GLM-4-9B和ChatGLM3-6B 1.引言 1.1 开源文化简介 1.2 开源项目的重要性 1.3 博客目的和读者价值 2.什么是开源项目&#xff1f; 2.1 开源定义 2.2 开源许可证类型 2.3 开源社区的作用 3.为什么程序员应该关注开源项目&#xff…

如何在Ubuntu 22.04中还原默认终端:解决无法打开终端的问题

我之前安装了xterm和新的Python&#xff0c;无法打开ubuntu自带的gnome-terminalle 。 终端应用崩溃&#xff1a; 试着通过其他方式打开终端&#xff0c;例如按下 CtrlAltT。 尝试使用其他终端模拟器&#xff0c;例如 xterm、konsole 或 gnome-terminal。可以通过 AltF2 然后…

IDM究竟有哪些优势?一探究竟,揭开下载利器的神秘面纱

在当今互联网信息爆炸的时代&#xff0c;下载工具已经成为我们日常生活中不可或缺的一部分。Internet Download Manager&#xff08;IDM&#xff09;以其强大的功能和高效的性能&#xff0c;赢得了广大用户的青睐。那么&#xff0c;IDM究竟有哪些优势使其在众多下载工具中脱颖而…

整蛊软件/插件使用方法与配置步骤~

今天出一期整蛊软件的使用方法与配置步骤 很多人在使用整蛊软件的时候 想自己添加更多的玩法内容 但是还不知道如何去配置 这期给大家出一下图文教程步骤 基本上也是软件的功能介绍使用方式~ 案例可扫码查看 第一步&#xff1a;打开软件输入卡密登录&#xff1a; 卡密费用&…

最经济实惠的通配符SSL证书是哪款?

网络安全已成为企业和个人网站运营者关注的焦点。SSL证书作为确保数据传输安全的关键工具&#xff0c;其重要性不言而喻。特别是通配符SSL证书&#xff0c;因其能够为一个主域名及其所有子域名提供统一的安全保护&#xff0c;而受到广泛欢迎。但面对市场上众多的SSL证书品牌和价…

[大模型]Qwen2-7B-Instruct 接入 LangChain 搭建知识库助手

环境准备 在 autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.1.0–>3.10(ubuntu20.04)–>12.1 接下来打开刚刚租用服务器的 JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下载和运行 demo。 pip 换源…

mysql中社区版如何杀死锁

在MySQL中&#xff0c;特别是社区版&#xff0c;当遇到锁问题时&#xff0c;你可能需要杀死锁定资源的进程来解决问题。以下是一些步骤和相关信息&#xff0c;用于在MySQL中杀死锁定的进程&#xff1a; 查看当前进程&#xff1a; 首先&#xff0c;你需要查看当前MySQL中的所有…

One能聊天接入百度千帆AppBuilder

One能聊天介绍:基于ChatGPT实现的微信小程序,适配H5和WEB端。包含前后端,支持打字效果输出流式输出,支持AI聊天次数限制,支持分享增加次数等功能One能聊天开源地址:https://github.com/oldinaction/ChatGPT-MPOne能聊天演示环境:可关注【阿壹族】公众号,并回复【One能聊…

MySQL复制机制详解:主从复制与GTID复制的配置与管理

引言: MySQL复制是MySQL数据库的一项重要功能,它允许数据从一个MySQL数据库服务器(被称为主服务器)复制到一个或多个MySQL数据库服务器(被称为从服务器)。主要目的是为了实现数据冗余和备份,提高数据的可用性和读取性能。 主从复制(Master-Slave Replication)是最常…

12_YouOnlyLookOnce(YOLOv3)新一代实时目标检测技术

1.1 回顾V1和V2 V1&#xff1a;05_YouOnlyLookOnce(YOLOV1)目标检测领域的革命性突破-CSDN博客 V2&#xff1a;07_YouOnlyLookOnce(YOLOv2)Better&#xff0c;Faster&#xff0c;Stronger-CSDN博客 1.2 简介 YOLOv3&#xff08;You Only Look Once version 3&#xff09;是…

spring boot jwt 实现用户登录完整java

spring boot jwt 实现用户登录完整java 登录校验逻辑 用户登录的校验逻辑分为三个主要步骤&#xff0c;分别是校验验证码&#xff0c;校验用户状态和校验密码&#xff0c;具体逻辑如下 前端发送username、password、captchaKey、captchaCode请求登录。判断captchaCode是否为…

ubuntu 20.04禁止自动更新内核驱动、显卡驱动(使用命令行)

本文目录 一、禁止更新内核1.1 查看当前内核1.2 查看安装的内核1.3 根据需求&#xff0c;使用hold参数禁止固定内核1.4 查询被锁定不更新软件包的状态 二、禁止更新显卡驱动2.1 查看安装的显卡驱动2.2 查看详细的详细的显卡信息2.3 禁止显卡驱动更新2.4 查询显卡是否设置成功 前…

618网络机顶盒哪个牌子好?内行盘点网络机顶盒排行榜

因工作原因每天都在跟各种类型的网络机顶盒打交道&#xff0c;最近超多朋友问我网络机顶盒哪个牌子好&#xff0c;不知道如何挑选网络机顶盒&#xff0c;我将要分享目前最值得入手的网络机顶盒排行榜&#xff0c;想买网络机顶盒可以看看以下这些品牌&#xff1a; ★泰捷WEBOX 6…

【力扣】目标和

一、题目描述 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 &#xff0c;在 1 之前添加 - &a…

鸿蒙开发HarmonyOS Next 网络框架retrofit 封装 viemodel使用

新手刚开始学习harmonyos开发&#xff0c;之前搞安卓开发习惯使用retrofit,结果在三方库中还真搜到了&#xff0c;然后就模拟学习一下。有不对的地方请指点一下。新手新手 oh-package.json5 引入库 retofit 需要使用2.0.1-rc.0 以上版本&#xff0c;修复了retrofit发送网络请…