【JavaScript进阶】作用域解构箭头函数
目录
1、作用域
1.1 局部作用域
1.2 全局作用域
1.3 作用域链
1.4 JS垃圾回收机制
拓展-JS垃圾回收机制-算法说明
引用计数
标记清除法
1.5 闭包
1.6 变量提升
2、函数进阶
2.1 函数提升
2.2 函数参数
1. 动态参数
2. 剩余参数
展开运算符
展开运算符 or 剩余参数
2.3 箭头函数(重要)
2. 箭头函数参数
3. 箭头函数 this
3、解构赋值
3.1 数组解构
1. 立即执行函数
2. 数组解构
3.2 对象解构
遍历数组 forEach 方法(重点)
步骤 渲染商品列表案例
筛选数组 filter 方法(重点)
案例 商品列表价格筛选编辑
总结一下~本章节对我有很大的收获,希望对你也是!!!
本章节用到的所有资源材料都可以自取:素材自取
1、作用域
1.1 局部作用域
1. 函数内部声明的变量,在函数外部无法被访问2. 函数的参数也是函数内部的局部变量3. 不同函数内部声明的变量无法互相访问4. 函数执行完毕后,函数内部的变量实际被清空了
1. let 声明的变量会产生块作用域,var 不会产生块作用域2. const 声明的常量也会产生块作用域3. 不同代码块之间的变量无法互相访问4. 推荐使用 let 或 const
1.2 全局作用域
1. 为 window 对象动态添加的属性默认也是全局的,不推荐!2. 函数中未使用任何关键字声明的变量为全局变量,不推荐!!!3. 尽可能少的声明全局变量,防止全局变量被污染
1.3 作用域链
Ø 在函数被执行时,会 优先查找当前 函数作用域中查找变量Ø 如果当前作用域查找不到则会依次 逐级查找父级作用域 直到全局作用域
1. 嵌套关系的作用域串联起来形成了作用域链2. 相同作用域链中按着从小到大的规则查找变量3. 子作用域能够访问父作用域,父级作用域无法访问子级作用域
1.4 JS垃圾回收机制
Ø 全局变量一般不会回收(关闭页面回收);Ø 一般情况下局部变量的值, 不用了, 会被自动回收掉
总结:
Ø 简称 GCØ JS中内存的分配和回收都是自动完成的, 内存 在不使用的时候会被垃圾回收器 自动回收
Ø 不再用到的内存,没有及时释放,就叫做内存泄漏
Ø 内存分配、内存使用、内存回收Ø 全局变量一般不会回收; 一般情况下局部变量的值, 不用了, 会被自动回收掉
拓展-JS垃圾回收机制-算法说明
1. 栈(操作系统): 由 操作系统自动分配释放 函数的参数值、局部变量等,基本数据类型放到栈里面。2. 堆(操作系统): 一般由程序员分配释放,若程序员不释放,由 垃圾回收机制 回收。 复杂数据类型 放到堆里面。
引用计数
1. 跟踪记录被 引用的次数2. 如果被引用了一次,那么就记录次数1,多次引用会 累加 ++3. 如果减少一个引用就 减1 --4. 如果引用次数是 0 ,则释放内存
标记清除法
1. 标记清除算法将“不再使用的对象”定义为“ 无法达到的对象 ”。2. 就是从 根部 (在JS中就是全局对象)出发定时扫描内存中的对象。 凡是能从 根部到达 的对象,都是还 需要使用 的。3. 那些 无法 由根部出发触及到的 对象被标记 为不再使用,稍后进行 回收 。
标记所有的引用
还是拿这个互相指引的函数为例:
当函数执行结束的时候,此时已经没有入口能够找到这个互相指引的函数里的对象,所以会自动被垃圾回收机制清除!
Ø 从 根部 扫描对象,能查找到的就是使用的,查找不到的就要回收
1.5 闭包
简单理解: 闭包 = 内层函数 + 外层函数的变量
内层函数跟外层函数的变量产生捆绑关系!
闭包作用: 封闭数据,提供操作,外部也可以访问函数内部的变量
闭包应用: 实现数据的私有
但是有的人就可以直接对我的全局变量进行修改!这样是很不安全的:
此时函数却直接被修改成调用了1000次大大增加了程序运行的负担!
所以,此时就是需要闭包来对数据进行封闭,来实现数据的私有化!
此时能发现,虽然i在函数内部,但是fun却指向fn函数能够找到i,i又是外部函数的变量被引用,所以变相来说,i是会根据全局变量fun的生存周期来决定的,fun在页面关闭时被回收,i变量也是!
这里函数被调用完后,此时里面的变量应该是要被回收的,但是跟着fun的全局周期来进行生成,也就是说,这个i变量应该要被回收的,但是没有被回收,就会存在内存泄漏的问题!!!
Ø 闭包 = 内层函数 + 外层函数的变量
Ø 封闭数据,实现数据私有,外部也可以访问函数内部的变量Ø 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来
Ø 内存泄漏
1.6 变量提升
1. 变量在未声明即被访问时会报语法错误2. 变量在var声明之前即被访问,变量的值为 undefined3. let/const 声明的变量不存在变量提升4. 变量提升出现在相同作用域当中5. 实际开发中推荐先声明再访问变量

JS初学者经常花很多时间才能 习惯变量提升 ,还经常出现一些意想不到的bug,正因为如此,ES6 引入了块级作用域,用let 或者 const声明变量,让代码写法更加规范和人性化。
2、函数进阶
2.1 函数提升
函数的调用同样也能被执行!就是因为在代码执行的过程中,首先就是将所有的函数声明都提升到了当前作用域的最前面~
2.2 函数参数
1. 动态参数
2. 剩余参数
总结:
Ø 用于获取多余的实参
Ø 动态参数是伪数组Ø 剩余参数是真数组Ø 开发中使用剩余参数想必也是极好的
展开运算符
典型运用场景: 求数组最大值(最小值)、合并数组等
展开运算符 or 剩余参数
剩余参数: 函数参数使用,得到真数组展开运算符: 数组中使用, 数组展开
2.3 箭头函数(重要)
const fn = function () {
console.log(123)
}
// 箭头函数 基本语法
const fn = () => {
console.log(123)
}
fn()
const fn = (x) => {
console.log(x)
}
fn(1)
// 1. 只有一个形参的时候 可以省略小括号
const fn = x => {
console.log(x)
}
fn(2)
// 2.只有一行代码的时候 可以省略大括号
const fn = x => console.log(x)
fn(11)
const fn = x => {
return x + x
}
console.log(fn(1))
// 等价
const fn = x => x + x
console.log(fn(2))
// 直接返回一个对象
const fn = (uname) => ({ uname: uname })
//因为对象是要用{}包括起来 所以用()包起来
console.log(fn('溜得滑'))
总结:
1. 箭头函数属于表达式函数,因此不存在函数提升2. 箭头函数只有一个参数时可以省略圆括号 ()3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回4. 加括号的函数体返回对象字面量表达式
2. 箭头函数参数
Ø 没有arguments动态参数Ø 可以使用剩余参数
3. 箭头函数 this
3、解构赋值
3.1 数组解构
1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量2. 变量的顺序对应数组单元值的位置依次进行赋值操作
1. 立即执行函数
2. 数组解构
// 1.变量多 单元值少 undefined
const [a, b, c] = [1, 2]
console.log(a)
console.log(b)
console.log(c) //undefined
// 2.变量少 单元值多
const [a, b] = [1, 2, 3]
console.log(a)
console.log(b)
// 3.变量少 单元值多
const [a, b, ...c] = [1, 2, 3, 4]
console.log(a)
console.log(b)
console.log(c) //[3, 4]
// 4.变量给初始值
const [a = 0, b = 0] = [1, 2]
console.log(a) // 1
console.log(b) // 2
const arr = [1, 2, [3, 4]]
console.log(arr[0]) // 1
console.log(arr[1]) // 2
console.log(arr[2]) // [3,4]
console.log(arr[2][0]) // 3
3.2 对象解构
1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量2. 对象属性的值将被赋值给与属性名 相同的 变量3. 注意解构的变量名不要和外面的变量名冲突否则报错4.对象中找不到与变量名一致的属性时变量值为 undefined
3. 多级对象解构:
数组多级对象解构:
多级对象解构案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<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
// function render(arr) {
function render({ data }) {
// 我们只要 data 数据
// 内部处理
// const { data } = msg
console.log(data)
}
render(msg)
// 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myData
function render({ data: myData }) {
// 要求将 获取过来的 data数据 更名为 myData
// 内部处理
console.log(myData)
}
render(msg)
</script>
</body>
</html>
遍历数组 forEach 方法(重点)
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数主要使用场景: 遍历数组的每个元素
1. forEach 主要是遍历数组2. 参数当前数组元素是必须要写的, 索引号可选。
步骤 渲染商品列表案例
案例自取:素材自取
活动栏切换:纯css 不需要js
筛选数组 filter 方法(重点)
const arr = [10, 20, 30]
// 筛选数组filter
const newArr = arr.filter(function (item, index) {
console.log(item)
console.log(index)
return index >= 20
})
console.log(newArr) //[20,30]
// 返回符合条件的新数组
const newArr = arr.filter(item => item >= 20)
console.log(newArr)
返回值: 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组参数: currentValue 必须写, index 可选
案例 商品列表价格筛选
案例自取:素材自取 
第一步:创建渲染函数,获取goodList 数组后,取到所有的数据存入str内!将str追加给list进行渲染!

第二步,进行筛选过滤通过不同点击的data-index 然后来进行筛选商品的价格分别存入arr内,然后再次进行渲染

JavaScript:
function render(goodsList) {
let str = ''
goodsList.forEach(item => {
const { id, name, price, picture } = item
// console.log(id)
str += `
<div class="item">
<img src="${picture}" alt="">
<p class="name">${name}</p>
<p class="price">${price}</p>
</div>
`
});
//追加给list
document.querySelector('.list').innerHTML = str
}
render(goodsList)
// 2.筛选过滤
document.querySelector('.filter').addEventListener('click', e => {
// e.target.data.index e.target.tagName
const { tagName, dataset } = e.target
// 判断
if (tagName === 'A') {
// console.log(11)
let arr = goodsList
if (dataset.index === '1') {
arr = goodsList.filter(item => item.price > 0 && item.price <= 100)
}
else if (dataset.index === '2') {
arr = goodsList.filter(item => item.price > 100 && item.price <= 300)
}
else if (dataset.index === '3') {
arr = goodsList.filter(item => item.price > 300)
}
// console.log(arr)
render(arr)
}
})
总结一下~本章节对我有很大的收获,希望对你也是!!!