本文是我在学习过程中记录学习的点点滴滴,目的是为了学完之后巩固一下顺便也和大家分享一下,日后忘记了也可以方便快速的复习。
ES6高级语法(一)
- 前言
- 一、垃圾回收机制(Garbage Collection)
- 1.1、引用计数法
- 1.2、标记清除法(引用计数法升级版)
- 1.3、内存泄漏
- 二、闭包
- 三、函数进阶(函数参数默认值、动态参数、剩余参数)
- 3.1、函数提升
- 3.2、函数参数
- 3.2.1、默认值
- 3.2.2、动态参数
- 3.3.3、剩余参数(...)
- 3.3、箭头函数
- 3.3.1、箭头函数参数
- 3.3.2、箭头函数 this
- 四、解构赋值(左边是[]还是{}取决于“=”右边是数组还是对象)
- 4.1、数组解构
- 4.2、对象解构
- 五、forEach遍历数组
- 六、filter筛选数组
前言
今天学习的主要是关于ES6新语法知识的理解和应用
一、垃圾回收机制(Garbage Collection)
栈负责存放简单数据类型,堆负责存放复杂数据类型,但是复杂数据类型会把内容存在堆中,在栈中会存一个变量指向堆中的数据。垃圾回收就是将不再使用的对象的那片内存回收。
栈:存放简单数据类型、局部变量、参数等,由系统自动分配和释放。
堆:存放复杂数据类型,由程序员分配和释放,程序员不释放则由垃圾回收机制回收。所以垃圾回收机制一般回收复杂数据类型。
1、全局变量一般不会回收(关闭页面才会回收)
2、局部变量没有引用了,用完即被回收
3、垃圾回收机制一般回收复杂数据类型
1.1、引用计数法
当一个变量、函数、对象被别的地方引用了一次,则该变量的引用次数加一,减少引用一次 则减一,直至为0则被释放。
缺陷:如果两片内存互相引用则一直不会被垃圾回收机制回收,就会出现内存泄漏问题。
1.2、标记清除法(引用计数法升级版)
1、将“不再使用的对象”定义为“无法到达的对象”。
2、从根部定时的扫描内存中对象,凡是能从根部到达的对象,都是还需要使用的,凡是到达不了的就是认为不再需要,即便它们互相引用也会被清除,因为它们处于游离态,从根部不能到达。
1.3、内存泄漏
由于某种原因某片内存无法被垃圾回收机制回收或无法被释放,则成为内存泄漏,内存泄漏多了可能导致内存溢出。
二、闭包
概述:
一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。外层函数内定义了一个内层函数,内层函数需要访问外层函数的变量。
作用:
1、让一个函数访问另一个函数内部的变量成为可能。主要运用就是用来实现数据私有化,将一个变量写在一个函数内,再在这个函数内写一个函数来负责操作该变量,然后return该变量,这时要改变该变量就只能调用这个内部函数来改变,这样就实现了变量的私有化,保护变量不被污染。(使用了闭包的话,该变量不会被回收,因为使用闭包使得外部变量(全局变量)指向该变量或函数,所以这个函数不会被销毁,只有当页面被关闭才会被销毁,所以使用闭包可能会引起内存泄漏,因为这个变量没有被正常回收)
2、闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来
==代码:==从代码形式上看闭包是一个做为返回值的函数,如下代码所示:
<script>
// 1. 闭包 : 内层函数 + 外层函数变量
// function outer() {
// const a = 1
// function f() {
// console.log(a)
// }
// f()
// }
// outer()
// 2. 闭包的应用: 实现数据的私有。统计函数的调用次数
// let count = 1
// function fn() {
// count++
// console.log(`函数被调用${count}次`)
// }
// 3. 闭包的写法 统计函数的调用次数
function outer() {
let count = 1
function fn() {
count++
console.log(`函数被调用${count}次`)
}
return fn
}
const re = outer()
// const re = function fn() {
// count++
// console.log(`函数被调用${count}次`)
// }
re()
re()
// const fn = function() { } 函数表达式
// 4. 闭包存在的问题: 可能会造成内存泄漏
</script>
三、函数进阶(函数参数默认值、动态参数、剩余参数)
3.1、函数提升
概念:
函数可以在声明之前调用,因为系统会把所有函数声明提升到当前作用域的最前面,和变量提升差不多,变量提升只提升变量声明,不提升变量赋值;函数提升只提升函数声明,不提升函数调用。
使用var fun=funtion(){}这种表达式的声明不存在提升现象
代码:
<script>
// 调用函数
foo()
// 声明函数
function foo() {
console.log('声明之前即被调用...')
}
// 不存在提升现象
bar() // 错误
var bar = function () {
console.log('函数表达式不存在提升现象...')
}
</script>
3.2、函数参数
3.2.1、默认值
总结:
- 声明函数时为形参赋值即为参数的默认值
- 如果参数未自定义默认值时,参数的默认值为
undefined
- 调用函数时没有传入对应实参时,参数的默认值被当做实参传入
<script>
// 设置参数默认值
function sayHi(name="小明", age=18) {
document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);
}
// 调用函数
sayHi();//不传参数就是用参数默认值name="小明", age=18
sayHi('小红');
sayHi('小刚', 21);
</script>
3.2.2、动态参数
概念:
arguments
是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参,伪数组与真数组的区别就是伪数组没有那些真数组的方法,例如push、pop、slice等等。
总结:
1.arguments
是一个伪数组
2. arguments
的作用是动态获取函数的实参
传入未指定数量的参数时可以用arguments
<script>
// 求生函数,计算所有参数的和
function sum() {
// console.log(arguments)
let s = 0
for(let i = 0; i < arguments.length; i++) {
s += arguments[i]
}
console.log(s)
}
// 调用求和函数
sum(5, 10)// 两个参数
sum(1, 2, 4) // 两个参数
</script>
3.3.3、剩余参数(…)
剩余参数...和展开运算符...比较容易混淆,但是剩余参数...只存在于函数中
总结:
...
是语法符号,置于最末函数形参之前,用于获取多余的实参- 借助
...
获取的剩余实参,是个真数组,拥有push、pop、shift、unshift等数组方法
传入指定数量或以上的参数时可以用...xxx
<script>
function config(baseURL, ...other) {
console.log(baseURL) // 得到 'http://baidu.com'
console.log(other) // other 得到 ['get', 'json']
}
// 调用函数
config('http://baidu.com', 'get', 'json');
</script>
3.3、箭头函数
概念:
箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。
箭头函数的用法就是用来替换表达式函数(let fun=funtion(){}),简化表达式函数
总结:
- 箭头函数属于表达式函数,因此不存在函数提升
- 箭头函数只有一个参数时可以省略圆括号
()
- 箭头函数函数体只有一行代码时可以省略花括号
{}
,并自动做为返回值被返回
<script>
//0. 常规函数写法
// 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>
3.3.1、箭头函数参数
箭头函数中没有 arguments
,只能使用 ...
动态获取实参
<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, 4)
console.log(result) // 9
</script>
3.3.2、箭头函数 this
箭头函数不会创建自己的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) // obj
let i = 10
const count = () => {
console.log(this) // obj
}
count()
}
}
obj.sayHi()
</script>
四、解构赋值(左边是[]还是{}取决于“=”右边是数组还是对象)
解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。
4.1、数组解构
数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法,如下代码所示:
<script>
// 普通的数组
let arr = [1, 2, 3]
// 批量声明变量 a b c
// 同时将数组单元值 1 2 3 依次赋值给变量 a b c
let [a, b, c] = arr
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
</script>
总结:
- 赋值运算符
=
左侧的[]
用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量 - 变量的顺序对应数组单元值的位置依次进行赋值操作
- 变量的数量大于单元值数量时,多余的变量将被赋值为
undefined
- 变量的数量小于单元值数量时,可以通过
...
获取剩余单元值,但只能置于最末位 - 允许初始化变量的默认值,且只有单元值为
undefined
时默认值才会生效
4.2、对象解构
对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法,如下代码所示:
<script>
// 普通对象
const user = {
name: '小明',
age: 18
};
// 批量声明变量 name age
// 同时将数组单元值 小明 18 依次赋值给变量 name age
const {name, age} = user
console.log(name) // 小明
console.log(age) // 18
</script>
总结:
- 赋值运算符
=
左侧的{}
用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量 - 对象属性的值将被赋值给与属性名相同的变量
- 对象中找不到与变量名一致的属性时变量值为
undefined
- 允许初始化变量的默认值,属性不存在或单元值为
undefined
时默认值才会生效
注:支持多维解构赋值:
<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名字混淆,要求渲染函数里面的数据名改为 myData
function render({ data: myData }) {
// 要求将 获取过来的 data数据 更名为 myData
// 内部处理
console.log(myData)
}
render(msg)
</script>
五、forEach遍历数组
概念:
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数
注意:
1.forEach 主要是遍历数组
2.参数item当前数组元素是必须要写的, 索引号index可选。
<script>
// forEach 就是遍历 加强版的for循环 适合于遍历数组对象
const arr = ['red', 'green', 'pink']
const result = arr.forEach(function (item, index) {
console.log(item) // 数组元素 red green pink
console.log(index) // 索引号
})
// console.log(result)
</script>
六、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>
💕 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力! \textcolor{orange}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐ 收藏,你的青睐是我努力的方向! \textcolor{red}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
🥕 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!