JavaScript进阶 第一天

news2024/12/23 10:53:21
  • 作用域
  • 函数进阶
  • 解构赋值

一.作用域

  • 局部作用域
  • 全局作用域
  • 作用域链
  • JS垃圾回收机制
  • 闭包
  • 变量提升

1.1 作用域

① 概念:规定了变量能够被访问的“范围”,离开了这个"范围",变量不能被访问

② 分类

  • 局部作用域

      (1)函数作用域:在函数内部声明的变量,只能在函数内部被访问,外部无法直接访问

1.函数内部声明的变量,在函数外部无法被访问

2.函数的参数也是函数内部的局部变量

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

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

      (2)块作用域:在JavaScript中使用{ }包裹起来的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问

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

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

3.不同代码之间的变量无法相互访问

4.推荐使用let或const

  • 全局作用域

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

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

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

④ 函数中未使用任何关键字声明的变量为全局变量

⑤ 尽可能少声明全局变量,防止全局变量被污染

1.2 作用域链

① 概念:本质是底层的变量查找机制

  • 在函数被执行时,会优先在当前函数作用域中查找变量
  • 如果当前作用域找不到会依次逐级查找父作用域直到全局作用域

总结

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

2.相同作用域链中按照从小到大的规则查找变量

3.子作用域能够访问父作用域,父级作用域无法访问子级作用域

1.3.垃圾回收机制

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

内存的生命周期

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

③ 说明

  • 全局变量一般不会回收(关闭页面回收)
  • 一般情况下,局部变量的值,不用了,会被自动回收掉

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

⑤ 算法说明

堆和栈的分配说明:

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

2.堆(操作系统):一般由程序员分配释放,如果程序员不释放,由垃圾回收机制回收,一般存放复杂数据类型

两种常见的垃圾回收算法:引用计数法和标记清除法

引用计数:

  • IE浏览器采用的是引用计数法,定义“内存不再使用”,就是看一个对象是否有指向它的引用,如果没有就回收
  • 跟踪记录被引用的次数
  • 如果被引用了依次,就记录一次,多次引用会累加++
  • 如果减少一个引用就减1
  • 如果引用次数是0,就释放内存

致命问题:

嵌套引用(循环引用):如果两个对象下相互引用,垃圾回收器不会进行回收,就会导致内存泄漏,因为引用次数永远不会为0

标记清除法

  • 现代浏览器已经不再使用引用计数算法了,大多是基于标记清除法的某些改进算法
  • 标记清除算法将"不再使用的对象"定义为"无法达到的对象"
  • 就是从根部(在JS中就是全局对象)触发定时扫描内存中的对象,凡是能够从根部到达的对象都是需要使用的
  • 无法从根部触发触及到的对象被标记为不再使用,稍后进行回收

 1.4.闭包

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

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

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

 ④ 基本格式:

 ⑤ 闭包的应用:实现数据的私有

function count () {
//  数据私有  i不会被回收, 可能会有内存泄漏的问题
    let i = 0
function fn () {
     i++
     console.log(i)
}
   return fn
}
const fun = count()
fun() 

 1.5.变量提升(不建议使用)

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

  • 把所有var声明的变量提升到当前作用域的最前面
  • 只提升声明,不提升赋值

相当于:

var num
console.log(num + '件')

② 注意

  • 变量在未声明即被访问时会报语法错误
  • 变量在var声明之前即被访问,变量的值为undefined
  • let/ const 声明的变量不存在变量提升
  • 变量提升出现在相同作用域中
  • 实际开发中推荐先声明再访问变量

二.函数进阶

  • 函数提升
  • 函数参数
  • 箭头函数

2.1 函数提升

  • 函数提升指的是把所有函数声明提升到当前作用域的最前面
  • 只提升函数声明,不提升函数调用
  • 函数表达式不支持提升
  • 函数提升出现在相同作用域中
// 1.会把所有函数声明提升到当前作用域的最前面
// 2.只提升函数声明,不提升函数调用
fn()
function fn() {
   console.log('函数提升')
}
// 函数表达式不支持将调用写到声明前面

2.2 函数参数

  • 动态参数
  • 剩余参数

动态参数

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

② 代码

 function getSum() {
    console.log(arguments);
    let sum = 0
  for (let i = 0; i < arguments.length; i++) {
    sum += arguments[i]
  }
  console.log(sum)
}
getSum(1,2,3,4,5,6,7,8,9,10)

③ 注意

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

剩余参数

① 剩余参数

  • ...是语法符号,置于最末函数形参之前,用于获取多余的实参
  • 借助...获取到的剩余实参,是个真数组

② 代码

function getSum (a, b, ...arr) {
   console.log(arr)  // 使用的时候不需要使用...
}
getSum(2, 3)
getSum(1, 2, 3, 4, 5)

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

  • 展开数组,不会修改原数组
const arr1 = [1, 2, 3]
// 展开数组: 不会修改原数组 应用场景:求数组最大值(最小值), 合并数组
// 最大值
console.log(Math.max(...arr1))
console.log(Math.min(...arr1))
console.log(...arr1)
  • 合并数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5]
const arr = [...arr1, ...arr2]

④ 剩余参数和展开运算符的区别

剩余参数:在函数中使用,会得到一个真数组

展开运算符:数组中使用,数组展开

2.3 箭头函数

  • 基本语法
  • 箭头函数参数
  • 箭头函数this

1.基本语法

 ① 目的:引入箭头函数的目的是更加简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁

② 使用场景:箭头函数更适用于那些原本需要匿名函数的地方

③ 写法

(1)原本匿名函数写法

const fn = function () {
   console.log(123)
}

 (2)箭头函数基本写法

const fn = () => {
    console.log(123)
}

fn()

(3)箭头函数传参数

const fn = (x) => {
    console.log(x)
}
fn(1)

(4)只有一个参数的可以省略小括号

const fn = x => {
   console.log(x)
}
fn(1)

(5)只有一行代码,可以省略大括号

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

(6)只有一行代码,箭头函数可以省略return

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

(7)箭头函数可以直接返回一个对象

const fn = (uname) => ({ uname: uname })
console.log(fn('hello'))

2.箭头函数参数

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

3.箭头函数this

① this指向window

console.log(this)

② 普通函数this指向调用者

function fn () {
// this指向调用者
  console.log(this)
}

③ 对象里面的普通函数的this指向该对象

        const obj = {
            name: 'andy',
            sayHi: function () {
                console.log(this)
            }
        }
        obj.sayHi()

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

⑤ 普通函数箭头函数指向上一层作用域window

        const fn = () => {
            console.log(this)
        }
        fn()

⑥ 对象方法中的箭头函数中的this指向window

        const obj = {
            uname: 'pink老师',
            sayHi: () => {
                console.log(this)  // 指向 window
            }
        }
        obj.sayHi()

⑦ 这里的this指向obj

        const obj = {
            uname: 'pink老师',
            sayHi: function () {
                let i = 10
                const count = () => {
                    console.log(this) // obj
                }
                count()
            }
        }
        obj.sayHi()

注意:DOM事件回调函数为了方便,还是不太推荐使用箭头函数

2.4 解构赋值

  • 数组解构
  • 对象解构

1.数组解构

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

② 基本语法

  • 赋值运算符 = 左侧的[ ] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
  • 变量的顺序对应数组单元值的位置依次进行赋值操作
const arr = [100, 60, 80]
// 数组解构
const [max, min, avg] = arr
console.log(max, min, avg)

 交换两个变量的值

let a = 1
// 必须加分号
let b = 2;
[b, a] = [a, b]

③ 必须加分号的两种情况

(1)立即执行函数

(function() {})();

(2)数组解构

const str = 'pink'
;[1, 2, 3].map(function (item) {
   console.log(item)
})

③ 数组解构细节

  • 变量多,单元值少,多余的值为undefined
const [a, b, c, d] = [1, 2, 3]
console.log(a, b, c, d)
  • 变量少,单元值多, 多余的参数没有值接
const [a, b] = [1, 2, 3, 4]
  • 利用剩余参数解决
const [a, b, ...c] = [1, 2, 3, 4]
console.log(a, b, c)
  •  防止undefined传递, 可以给默认参数
const [a = 0, b = 0] = []
console.log(a, b)
  •  按需导入,忽略某些返回值
const [a, b, , c] = [1, 2, 3, 4]
console.log(a, b, c)
  • 多维数组
// 多维数组
const arr = [1, 2, [3, 4]]
console.log(arr[0])
console.log(arr[2][0])

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

2.对象解构

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

② 基本语法

  • 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
  • 对象属性的值将被赋值给与属性名相同的变量
  • 解构的变量名不要和外面的变量名冲突报错
  • 对象中找不到与变量名一致的属性时变量值为undefined
const obj = {
   uname: 'pink',
   age: 18
}

const { uname, age } = obj

③ 给新的变量名赋值:可以从一个对象中提取变量并同时修改新的变量名, 新名字在后面

const uname = 'hello'
const { uname: username, age } = obj
console.log(username)

④ 解构数组对象

const pig = [{
  uname: '佩奇',
  age: 18
}]
const [{ uname, age }] = pig
console.log(uname)
console.log(age)

⑤ 多级对象解构

        const pig = {
            name: '佩奇',
            family: {
                mother: '妈妈',
                father: '爸爸',
                sister: '乔治'
            },
            age: 6
        }

        const { name, family: { mother, father, sister } } = pig
        console.log(name, mother, father, sister)

⑥ 多级对象数组解构

        const person = [{
            name: '佩奇',
            family: {
                mother: '妈妈',
                father: '爸爸',
                sister: '乔治'
            },
            age: 6
        }
        ]
        const [{ name, family: { mother, father, sister } }] = person
        console.log(name, mother, father, sister)

3.forEach() 方法

① 作用:遍历数组中的每个元素,将元素传递给回调函数

② 场景:遍历数组的每个元素

③ 语法:

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

     // 函数体

})

const arr = ['red', 'green', 'pink']
arr.forEach(function(item, index) {
     console.log(item)
     console.log(index)
})

 ④ 注意

  • 主要用来遍历数组
  • 参数里面当前元素是必须要写的,索引号是可选的

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

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

相关文章

END-TO-END、SCALE HYPERPRIOR、Checkerboard梳理总结

8.9-8.15学习汇报 阅读《END-TO-END OPTIMIZED IMAGE COMPRESSION》、《VARIATIONAL IMAGE COMPRESSION WITH A SCALE HYPERPRIOR》、《Checkerboard Context Model for Efficient Learned Image Compression》 传统的图像或视频压缩方法通常分为多个步骤&#xff0c;包括变换…

android设置竖屏仍然跟随屏幕旋转怎么办

如题所问&#xff0c;我最近遇到一个bug&#xff0c;就是设置了摇感&#xff0c;然后有用户反馈说设置了手机下拉的系统设置-屏幕旋转-关闭。然后屏幕还是会旋转的问题。 首先&#xff0c;我们先从如何设置横竖屏了解下好了 设置横屏和竖屏的方法&#xff1a; 方法一&#x…

IPv6项目开发测试记录

一、环境 1、网口 IPv6地址 fd00:0:0:1::15 子网前缀长度 64 网关地址&#xff08;非必须&#xff09; fd00:0:0:1::1 二、云环境、面板机连云测试 1、面板机设置IPv4地址后可以访问fd00::100这个地址 2、初始化时候服务器地址输入匹配正则式&#xff1a;IPv6地址匹配正则…

基因型比值比(genotypic odds ratio)和等位基因比值比(allelic odds ratio)的计算

基因型比值比&#xff08;genotypic odds ratio&#xff09;和等位基因比值比&#xff08;allelic odds ratio&#xff09;是两个不同的概念。一般而言&#xff0c;通过PLINK、GCTA等工具计算得到的比值比指的是等位基因比值比。 以下是基因型比值比和等位基因比值比的各自计算…

8月12日上课内容 综合配置详解 四层+七层代理

后续内容概述&#xff1a; Ivs集群: keepalive:vip实现代理高可用 NAT VPN DR (DR最常用) 数据库:增制改查 备份 高可用 主从复制 读写分离 DBA 市场量小&#xff0c;从业者不多&#xff0c;工资一般般。 中间件: redis.* 分布式存储: ELK日志分析。kafka消息队列 监控zabb…

知识分享:如何将一张图片转换成短链接?

今天我们要分享的知识是&#xff1a;如何将一张图片转换成链接&#xff1f; 之前我们有介绍过在二维彩虹将图片转换成二维码的方法&#xff0c;那么其实将图片转成链接也非常简单&#xff01;在做电商运营创建商品详情页面、作家为在线小说设置封面图、产品运营、策划活动等等…

IDC报告深度解读:2023年CRM发展趋势分析

近期&#xff0c;国际数据公司&#xff08;IDC&#xff09;发布了2022年下半年《中国客户关系管理(CRM)SaaS市场跟踪研究报告》&#xff0c;根据报告显示&#xff0c;2022年下半年中国CRM SaaS市场规模达到 11.6 亿美金&#xff0c;同比增长25.4%&#xff0c;CRM占中国整体SaaS…

SpringCloud初识

微服务架构4个核心问题&#xff1a; 这四个问题围绕这我们去学的一些东西&#xff0c;是重点!!! 1.服务很多&#xff0c;客户端该如何访问&#xff1f; 2.这么多服务&#xff0c;服务之间该如何通信&#xff1f; 3.这么多服务&#xff0c;该如何治理&#xff1f; 4.服务挂了…

Python 基础语法 | 常量表达式,变量,注释,输入输出

常量和表达式 我们可以把 Python 当成一个计算器&#xff0c;来进行一些算术运算 print(1 2 - 3) # 0 print(1 2 * 3) # 7 print(1 2 / 3) # 1.6666666666666665注意&#xff1a; print 是一个 Python 内置的 函数可以使用 - * / () 等运算符进行算术运算&#xff0c;先…

postman接口测试工具的常规使用

postman接口测试工具简介与安装 Postman简介&#xff1a; Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。 它提供功能强大的Web API&HTTP请求调试。它能够发送任何类型的HTTP请求&#xff08;GET&#xff0c;HEAD&#xff0c;POST&#xff0c;PUT..&a…

04-基础入门-WEB源码拓展

基础入门-WEB源码拓展 1、WEB源码拓展&#xff08;1&#xff09;关于web源码目录结构&#xff08;2&#xff09;关于 WEB 源码脚本类型&#xff08;3&#xff09;关于 WEB 源码应用分类 2、演示案例&#xff08;1&#xff09;asp、php等源码测试&#xff08;2&#xff09;平台识…

我们常说这个pycharm里有陷阱,第三方库导入失败,看这里!

最近有小伙伴遇到了明明安装了 python 第三方库&#xff0c;但是在 pycharm 当中却导入不成功的问题。 ​ 一直以来&#xff0c;也有不少初学 python 的小伙伴&#xff0c;一不小心就跳进了虚拟环境和系统环境的【陷阱】中。 本文就基于此问题&#xff0c;来说说在 pycharm 当…

【leetcode】【图解】617. 合并二叉树

题目 难度&#xff1a;简单 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xf…

基于DBN的伪测量配电网状态估计,DBN的详细原理

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN的伪测量配电网状态估计 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN算法伪测量配电网…

leetcode 1171.从链表中删去总和值为零的连续节点

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;从链表中删去总和值为零的连续节点 思路&#xff1a; 在链表的 head 前新增加一个哨兵卫的头结点&#xff0c;方便计算前缀和。遍历链表&#xff0c;依次把每个节点的 val 相加到 sum 中去&#xff0c;再判断 sum 0 依…

网络编程(8.14)TCP并发服务器模型

作业&#xff1a; 1. 多线程中的newfd&#xff0c;能否修改成全局&#xff0c;不行&#xff0c;为什么&#xff1f; 2. 多线程中分支线程的newfd能否不另存&#xff0c;直接用指针间接访问主线程中的newfd,不行&#xff0c;为什么&#xff1f; 多线程并发服务器模型原代码&…

认识Transformer:入门知识

视频链接&#xff1a; https://www.youtube.com/watch?vugWDIIOHtPA&listPLJV_el3uVTsOK_ZK5L0Iv_EQoL1JefRL4&index60 文章目录 Self-Attention layerMulti-head self-attentionPositional encodingSeq2Seq with AttentionTransformerUniversal Transformer Seq2Seq …

排查docker无法启动问题

查看Linux系统操作日志(最后200行就可以排查)&#xff1a; tail -200f /var/log/messages

什么是证券股票交易接口?(股票交易挂单接口)源码开发步骤

证券股票交易接口是一种可以实现证券交易功能的软件接口&#xff0c;它提供了一组用于交易的函数或方法&#xff0c;可以通过调用这些接口来执行买卖股票、查询账户信息、获取市场行情等操作。证券股票交易接口可以连接到证券交易所或证券公司的交易系统&#xff0c;允许用户通…

SpringBoot基于Zookeeper实现分布式锁

文章目录 问题背景前言实现搭建Zookeeper容器引入依赖ZK客户端的配置类ZK客户端的工厂类注入bean构建测试类 问题背景 研究分布式锁&#xff0c;基于ZK实现&#xff0c;需要整合到SpringBoot使用 前言 参考自SpringBoot集成Curator实现Zookeeper基本操作&#xff0c;Zookeeper入…