
文章目录
- [Ⅰ. 变量与常量](#Ⅰ. 变量与常量)
- [Ⅱ. 模版字符串](#Ⅱ. 模版字符串)
- [Ⅲ. 对象](#Ⅲ. 对象)
- Ⅳ、解构赋值
- Ⅴ、箭头函数
- [Ⅵ. 数组的重要方法](#Ⅵ. 数组的重要方法)
-
- 一、概述
- [二、添加 `push()` 和 `unshift()`](#二、添加
push()和unshift()) - [三、删除 `pop()` 和 `shift()`](#三、删除
pop()和shift()) - [四、任意位置删除或添加 `splice()`](#四、任意位置删除或添加
splice()) - [五、包含 `includes()`](#五、包含
includes()) - [六、遍历 `forEach()`](#六、遍历
forEach()) - [七、过滤 `filter()`](#七、过滤
filter()) - [八、映射 `map()`](#八、映射
map()) - [九、检测每一个 `every()`](#九、检测每一个
every()) - [十、汇总 `reduce()`](#十、汇总
reduce())
- [Ⅶ. 对象的重要方法 `Object.keys()`](#Ⅶ. 对象的重要方法
Object.keys()) - [Ⅷ. 扩展运算符 `...`](#Ⅷ. 扩展运算符
...) - [Ⅸ. 序列化和反序列化](#Ⅸ. 序列化和反序列化)
- [Ⅹ. Web存储](#Ⅹ. Web存储)
- [十一. `Promise` + `Async`/`Await`](#十一.
Promise+Async/Await) -
- [一、为什么需要 `Promise`](#一、为什么需要
Promise) - [二、`Promise` 介绍](#二、
Promise介绍) - [三、`Promise` 的三种状态](#三、
Promise的三种状态) - 四、基本使用
- 五、消除上述回调地狱
- 六、Async+Await异步终极解决方案
- [一、为什么需要 `Promise`](#一、为什么需要
- [十二. 模块化](#十二. 模块化)
Ⅰ. 变量与常量
一、变量
javascript
let name = 'Jack'
let age = 18
name = 'Bit'
age = 20
二、常量
javascript
const PI = 3.14
const articleList = []
const user = {
name: 'vue3',
age: 9
}
三、思考
- const 声明的数组可以添加或删除么?
- const 声明的对象可以添加或修改属性么?
答:可以的,因为数组和对象在 js 中属于引用类型,对其做添加、删除等操作,并不改变其内存地址。
javascript
const arr = [1,2,3]
// 添加
arr.push(4)
console.log(arr)
// 删除
arr.shift()
console.log(arr)
const obj = {
name: 'vue3',
age: 9
}
// 添加属性
obj.birth = 2015
console.log(obj)
// 修改属性
obj.age = 10
console.log(obj)
Ⅱ. 模版字符串
一、普通字符串
用一对单引号或双引号声明,基本都用单引号
javascript
// 普通字符串
let name = 'Jack'
let msg = "Hello World"
二、模版字符串
用一对反引号声明
javascript
let name = `Jack`
let msg = `Hello World`
三、好处
1. 可任意换行
javascript
const htmlStr = '<div class="hot-goods-box"><h1>热门商品</h1><p>卖爆了卖爆了卖爆了</p></div>'
const htmlStr = `<div class="hot-goods-box">
<h1>热门商品</h1>
<p>卖爆了卖爆了卖爆了</p>
</div>`
2. 可嵌入表达式
避免了繁琐的加号做字符串拼接;嵌入的语法为 ${表达式}
javascript
let name = 'liren'
let age = 9
// 把 name,age 变量的值放到 xxx 的位置, 并且展示是否成年
// let str = 'My name is xxx, I am xxx years old, 未成年 or 已成年'
// 传统的加号拼接
// let str = 'My name is ' + name + ', I am ' + age + ' years old' + (age >= 18 ? '已成年' : '未成年')
// 模版字符串嵌入表达式
let str = `My name is ${name}, I am ${age} years old, ${age >= 18 ? '已成年' : '未成年'}`
Ⅲ. 对象
一、取值
1. 点取值
javascript
const obj = {
name: 'vue3',
age: 9
}
console.log(obj.name)
console.log(obj.age)
// 等同于
console.log(obj['name'])
console.log(obj['age'])
2. 中括号取值
javascript
const obj = {
name: 'vue3',
age: 9
}
let x = 'name'
let y = 'age'
// 正确的
console.log(obj[x])
console.log(obj[y])
// 错误的
console.log(obj.x)
console.log(obj.y)
3. 注意
当属性名是变量的时候,只能用中括号取值;否则既可以用点,也可以用中括号
二、简写
1. 属性
当属性名和属性值的名字一样时,并且配合变量时,可以简写
javascript
let min = 1
let max = 99
// 以前的写法(不简写)
const obj = {
min: min,
max: max
}
// 现在的写法
const obj = {
min,
max
}
2. 方法
javascript
const obj = {
// 不简写
fn: function() {
}
}
// 等同于
const obj = {
// 简写: 连同 :和function 一起省略
fn() {
}
}
Ⅳ、解构赋值
一、针对的目标
数组或对象
二、作用
让数组和对象的取值更便捷
三、代码示例
1. 数组解构
javascript
const arr = [11, 22, 33]
// eg1: 把 arr 中的3个值分别赋值给变量 a, b, c
// 以前的写法
let a = arr[0]
let b = arr[1]
let c = arr[2]
// 现在的写法
let [a, b, c] = arr
// eg2: 把 arr 中的后两个值赋值给变量 b,c
let [,b,c] = arr
// eg3: 把 arr 中的第1个值赋值给变量 a, 剩余的全部给到变量 rest
let [a, ...rest] = arr
2. 对象解构
javascript
const obj = {
name: 'lirendada',
age: 9,
address: '广东省广州市越秀区'
}
// eg1: 把 obj 中的3个属性值分别赋值给变量 name, age, address
// 以前的写法
const name = obj.name
const age = obj.age
const address = obj.address
// 现在的写法
const { name, age, address } = obj
// eg2: 把 obj 的 age, address 属性值赋值给 age, address
const { age, address } = obj
// eg3: 把 obj 的 name 属性值赋值给变量 name, 剩余的全部给到变量 rest
const { name, ...rest } = obj
// eg4: 把 obj 的 name 属性值赋值给变量 uname
const { name: uname } = obj
Ⅴ、箭头函数
一、非箭头函数
javascript
// 有名函数
function fn() {
// some code...
}
// 函数表达式
const fn = function() {
// some code...
}
二、语法
javascript
const fn = () => {
// some code...
}
const add = (x, y) => {
return x + y
}
三、特点
-
参数一个可以省小括号、函数体一句话可以省略大括号
javascriptconst log = arg => { console.log(arg) } -
当省略了大括号时,函数自带
returnjavascriptconst add = (x, y) => x + y // 等同于 const add = (x, y) => { return x + y } -
当函数体直接返回一个对象,如果简写,需要给对象加一对小括号
javascriptconst state = () => ({ token: 'xxxx', userInfo: { name: 'admin', id: 1 } }) // 等同于 const state = () => { return { token: 'xxxx', userInfo: { name: 'admin', id: 1 } } }
四、应用
可用于普通函数的声明,也多用于回调函数传参
javascript
setTimeout(() => {
}, 2000)
Ⅵ. 数组的重要方法
一、概述
数组是 js 的重要数据结构,掌握对数组的操作显得格外重要
二、添加 push() 和 unshift()
javascript
const arr = [11, 22, 33]
// 尾部添加
const len = arr.push(44)
console.log(len) // 4
// 头部添加
const len = arr.unshift(44)
console.log(len) // 4
三、删除 pop() 和 shift()
javascript
const arr = [11, 22, 33]
// 尾部删除
const last = arr.pop()
console.log(last) // 33
// 头部删除
const first = arr.shift()
console.log(first) // 11
四、任意位置删除或添加 splice()
javascript
const arr = [11, 22, 33, 44]
// 语法:
// arr.splice(startIndex:number, delCount:number, ...addItem)
// 删除 22
const temp = arr.splice(1, 1)
console.log(temp) // [22]
console.log(arr) // [11, 33, 44]
// 33后面添加55
arr.splice(2, 0, 55)
console.log(arr) // [11, 22, 33, 55, 44]
五、包含 includes()
javascript
const arr = [11, 22, 33, 44]
console.log(arr.includes(33)) // true
console.log(arr.includes(55)) // false
六、遍历 forEach()
javascript
const arr = [11, 22, 33, 44]
// for循环遍历
for(let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
// forEach遍历
arr.forEach((item, index, array) => {
// item: 每次遍历的元素
// index: 元素的下标
// array: 数组本身
})
七、过滤 filter()
保留满足条件的、去掉不满足条件的
javascript
const arr = [11, 22, 33, 44]
// 语法:
const filteredArr = arr.filter((item, index, array) => {
// 内部会遍历数组, 每遍历一次都会执行回调一次
// 如果返回true,则当前元素会保留; 否则去掉
return 布尔值
})
// 保留所有的偶数
const eventArr = arr.filter((item) => {
if(item % 2 === 0) {
return true
} else {
return false
}
})
// 简写
const eventArr = arr.filter((item) => item % 2 === 0)
八、映射 map()
由一个数组得到另一个数组,并且二者长度相同、每个元素存在一一对应关系
javascript
const arr = [11, 22, 33, 44]
// 得到 [22, 44, 66, 88]
// 语法:
const mappedArr = arr.map((item, index, array) => {
return 新值
})
// 得到每个元素翻倍的新数组
const doubleArr = arr.map((item) => {
// 原来每个元素乘 2
return item * 2
})
// 简写
const doubleArr = arr.map((item) => item * 2)
九、检测每一个 every()
javascript
const arr = [11, 22, 33, 44]
// 语法:
arr.every((item, index, array) => {
// 1、如果返回true, 说明当前元素满足条件, 则继续检测下一次;
// 若都满足条件, 则最终返回true
// 2、如果返回false, 说明当前元素不满足条件;
// 立即停止检测, 最终返回false
return 布尔值
})
// 判断arr中的元素是否都是奇数
const bool = arr.every((item) => {
console.log(item)
return item % 2 === 1
})
// 判断arr中的元素是否都大于10
const bool = arr.every((item) => {
console.log(item)
return item > 10
})
十、汇总 reduce()
javascript
const arr = [11, 22, 33, 44]
// 语法:
const result = arr.reduce((prev, item, index, array) => {
return 结果
}, 初始值)
// 对arr求和
const sum = arr.reduce((prev, item) => {
return prev + item
}, 0)
// 简写
const sum = arr.reduce((prev, item) => prev + item, 0)
// 商品列表数组
const goodsList = [
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 3 },
{ id: 3, name: '书籍', num: 2 }
]
// 求总数量
const totalNum = goodsList.reduce((prev, item) => prev + item.num, 0)
Ⅶ. 对象的重要方法 Object.keys()
javascript
const obj = {
id: 10001,
name: 'liren',
age: 9,
address: '广东省广州市越秀区'
}
// 之前遍历对象: for-in循环
for(let key in obj) {
console.log(key, obj[key])
}
// 获取对象键的数组
const keys = Object.keys(obj)
console.log(keys)// ['id', 'name', 'age']
// 可用来遍历对象
Object.keys(obj).forEach(key => {
console.log(obj[key])
})
// Object.keys()拿到的是键的数组,可以对数组做很多处理在进行遍历对象
// 需求:获取 obj 所有以 a 开头的属性值
Object
.keys(obj)
.filter(key => key.startsWith('a'))
.forEach(key => {
console.log(key, obj[key])
})
Ⅷ. 扩展运算符 ...
一、复制数组或对象
javascript
const arr1 = [11, 22, 33]
// 赋值
const arr2 = arr1
arr2.push(44)
console.log(arr1) // 受影响了
// 正确的做法, 把 arr1 复制一份给到 arr2
const arr2 = [...arr1]
const obj1 = {
id: 10001,
name: 'Bit',
age: 9
}
// 赋值
const obj2 = obj1
obj2.age = 10
console.log(obj1) // 受影响了
// 正确的做法, 把 obj1 复制一份给到 obj2
const obj2 = {...obj1}
二、合并数组或对象
javascript
const arr1 = [1,2,3]
const arr2 = [4,5,6]
// 把 arr1 和 arr2 合并起来给到 arr
const arr = [...arr1, ...arr2]
const obj1 = {
name: 'Jack',
height: 176
}
const obj2 = {
height: 180,
age: 18
}
// 把 obj1 和 obj2 合并起来给到 obj
// 注意: 同名属性会覆盖
const obj = {
...obj1,
...obj2
}
Ⅸ. 序列化和反序列化
一、序列化
把对象转换为json格式字符串
javascript
// 对象
const json = {
id: 10001,
name: 'liren',
age: 9
}
// 序列化
const jsonStr = JSON.stringify(json)
二、反序列化
把 json 字符串转换为 json 对象
javascript
// json字符串
const jsonStr = '{"id": 10001, "name": "liren", "age": 9}'
// 反序列化
const json = JSON.parse(jsonStr)
Ⅹ. Web存储
一、介绍
WebStorage 包含如下两种机制:
sessionStorage该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。- 仅为会话存储数据,这意味着数据将一直存储到浏览器(或选项卡)关闭。
- 数据永远不会被传输到服务器。
- 存储限额大于Cookie(最大5MB)。
localStorage即使浏览器关闭并重新打开也仍然存在。- 存储的数据没有过期日期,只能通过
JavaScript、清除浏览器缓存或本地存储的数据来清除。
- 存储的数据没有过期日期,只能通过
二、用法
以 localStorage 为例,学习存、取、删
1. 存
注意事项:存对象和数组时,需要先序列化!
javascript
// 存
localStorage.setItem(key:string, value:string)
// eg:
localStorage.setItem('uname', 'liren')
2. 取
如果 key 存在,则取出相应的值。
注意事项:取出对象和数组时,需要先反序列化!
javascript
// 取
localStorage.getItem(key:string)
// eg:
const uname = localStorage.getItem('uname')
3. 删
javascript
// 删
localStorage.removeItem(key:string)
十一. Promise + Async/Await
一、为什么需要 Promise
是为了消除回调地狱的
javascript
// 不使用promise之前,出现了回调地狱问题
// 需求: 延迟2秒之后输出1, 完了之后延迟1秒输出2, 完了之后延迟1秒输出3
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(2)
setTimeout(() => {
console.log(3)
}, 1000)
}, 1000)
}, 2000)
上述代码存在的问题:回调套回调, 代码的可读性差!
为了解决上述问题,Promise 就应运而生了!
二、Promise 介绍
Promise 是一个类,用来包装异步操作 ,根据异步操作的结果,是成功还是失败,进而决定 Promise 是成功还是失败;并且 Promise 支持链式调用,从而消除回调地狱!
三、Promise 的三种状态
- Pending:进行中
- Fulfilled:成功
- Rejected:失败
💥注意事项:
- 只能由
Pending -> Fulfilled,或Pending -> Rejected。 Promise的状态一旦确定,就不可改变了。
四、基本使用
javascript
const p = new Promise((resolve, reject) => {
// 编写异步代码:比如定时器、ajax请求等
setTimeout(() => {
// 2秒后, Promise标记为成功
resolve('ok')
reject('error')
}, 2000)
})
p.then((msg) => {
// 成功回调
console.log(msg)// ok
}, (err) => {
// 失败回调
console.log(err)// error
})
五、消除上述回调地狱
利用 Promise 来消除前面出现的回调地狱问题:
javascript
// 封装延迟函数
function delay(duration, n) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(n)
}, duration)
})
}
// 链式调用消除回调地狱
delay(2000, 1)
.then(n1 => {
console.log(n1)
return delay(1000, 2) // 必须要返回,外面才能链式调用,而不是继续在方法内调用,那就又变成回调地狱了
}).then(n2 => {
console.log(n2)
return delay(1000, 3)
}).then(n3 => {
console.log(n3)
})
上述代码虽然消除了回调地狱、但链式调用过长、也不利于阅读。
为了继续优化,Async + Await 就应运而生了。
六、Async+Await异步终极解决方案
- 在
Promise实例前添加await关键字,那么await的返回值就是当前Promise的resolve参数 await所在的函数必须被async修饰async函数内,以同步的方式执行
javascript
// 封装延迟函数(同上)
function delay(duration, n) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(n)
}, duration)
})
}
// 语法:
async function log() {
const n1 = await delay(2000, 1)
console.log(n1)
}
log()
// 最终代码
async function log() {
const n1 = await delay(2000, 1)
console.log(n1)
const n2 = await delay(1000, 2)
console.log(n2)
const n3 = await delay(1000, 3)
console.log(n3)
}
log()
十二. 模块化
一、概述
模块化是指将一个复杂程序划分为一系列独立、可互操作的模块的过程。每个模块负责特定的功能或任务,并通过定义好的接口与其他模块进行通信。简单来说,就是将代码进行分解、按功能进行管理。
模块化的目的是提高代码的可维护性、可重用性、可测试性和可扩展性。开发者能够更容易地处理大型 JavaScript 项目。
二、目录结构准备

- 新建 es-module 目录
- 命令行进入 es-module 目录
- 执行
npm init,初始化得到package.json文件 - 给
package.json添加"type": "module" - 根目录下新建
src/index.js、作为代码的入口文件 src目录下新建utils目录
三、默认导出与导入 export default && import
新建 utils/min.js 文件:
javascript
// 定义并默认导出求最小值函数
export default function min(m, n) {
return m > n ? n : m
}
💥注意事项: 默认导出 export default 在一个模块中最多出现 1 次。
src/index.js 文件:
javascript
// 默认导入
import min from './utils/min.js'
console.log(min(12, 45))
四、按需导出与导入 export && import
新建 utils/math.js 文件:
javascript
// 定义求和函数并按需导出
export function add(x, y) {
return x + y
}
// 定义作差函数并按需导出
export function sub(x, y) {
return x - y
}
💥注意事项: 按需导出 export 在一个模块中可以出现多次。
src/index.js 文件:
javascript
// 按需导入
import { add, sub } from './utils/math.js'
console.log(add(33, 18))
console.log(sub(33, 18))
