本视频不算长,一共4时36分钟,推荐1.25倍速观看,老师讲课风格幽默,知识点精炼,并未如题所说太深入讲解,讲课过程中声音会忽高忽低,并存在喷麦等情况,介意慎入
温故而知新,很多经典技术学了很久也一直在用,但还是比较喜欢偶尔拿些时间来看总结性的讲课视频,本人不喜欢一个视频看多遍,知识点都是一样的,多看几个优秀的教学视频,博采众长,能发现很多宝藏
# 一、ES6背景知识
# 1.1 ECMAScript 和 JavaScript
- ECMA 是标准,JS 是实现
- ECMAScript 简称 ECMA 或 ES
# 1.2 重要历史版本
- 1996, ES1.0 Netscape 将 JS 提交给 ECMA 组织,ES 正式出现
- 1999, ES3.0 被广泛支持
- 2011, ES5.1 成为 ISO 国际标准
- 2015, ES6.0 正式发布
# 1.3 ES6兼容性
- ES6(ES2015) 支持的环境 IE10+, Chrome, FireFox, 移动端, NodeJS
- 解决不兼容办法,编译、转换
- 在线转换
- 提前编译
- Babel 中文网
- Babel 入门教程 阮一峰
- Babel 是一个 JavaScript 编译器
- 一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行
- 现在就用 ES6 编写程序,而不用担心现有环境是否支持
# 二、变量 let 和 常量 const
# 2.1 var 的问题
- 可以重复声明,没有报错和警告
- 无法限制修改
- 只存在函数作用域,没有块级作用域,
{ }
- 弊端在闭包中体现的非常明显
# 2.2 let 和 const
- 不能重复声明
- 都是块级作用域,
{ }
块内声明的,块外无效 - let 是变量,可以修改
- const 是常量,不能修改
# 2.3 块级作用域举例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
window.onload= function () {
/*
var aBtn = document.getElementsByTagName('input')
for (var i=0; i < aBtn.length; i++) {
aBtn[i].onclick = function () {
alert(i)
}
}*/
var aBtn = document.getElementsByTagName('input')
for (let i = 0; i < aBtn.length; i++) {
aBtn[i].onclick = function () {
alert(i)
}
}
/*
var aBtn = document.getElementsByTagName('input')
for (var i = 0; i < aBtn.length; i++) {
// 封装到函数里,限制作用域
(function (i) {
aBtn[i].onclick = function () {
alert(i)
}
})(i)
}*/
}
</script>
</head>
<body>
<input type="button" value="按钮1">
<input type="button" value="按钮2">
<input type="button" value="按钮3">
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
结论分析:
- 原来用 var 的方式,结果弹出的都是 3
- 或者将变量 封装到函数里,限制作用域,但比较麻烦
- 用 let 最简单,直接 var 改 let,解决作用域问题
# 三、箭头函数
# 3.1 箭头函数的简写
- 如果只有一个参数,
()
可以省 - 如果只有一个
return
,{}
可以省
// 普通函数
function name() {
}
// 箭头函数,去掉 function, 加上 =>
let name = () => {
2
3
4
5
6
# 3.2 箭头函数注意点
(1)函数体内的this
对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new
命令,否则会抛出一个错误。
(3)不可以使用arguments
对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield
命令,因此箭头函数不能用作 Generator 函数。
# 四、扩展和解构赋值
# 4.1 参数扩展/展开
格式:...args
- 收集剩余的参数,必须当到最后一个参数位置
function show(a, b, ...args) {
console.log(a)
console.log(b)
console.log(args)
}
console.log(show(1, 2, 3, 4, 5))
// 1
// 2
// [3, 4, 5]
2
3
4
5
6
7
8
9
- 展开数组,简写,效果和直接把数组的内容写在这儿一样
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]
console.log(arr3)
// [1, 2, 3, 4, 5, 6]
2
3
4
5
- 设置默认值
function show2(a, b=5, c=8) {
console.log(a, b, c)
// 88 12 8
}
show2(88, 12)
2
3
4
5
# 4.2 解构赋值
let [a, b, c] = [1, 2, 3]
console.log(a, b, c)
// 1 2 3
let {x, y, z} = {x: 1, y: 2, z: 3}
console.log(x, y, z)
// 1 2 3
let [json, arr, num, str] = [{ a: 1, b: 2 }, [1, 2, 3], 8, 'str']
console.log(json, arr, num, str)
// { a: 1, b: 2 } [1, 2, 3] 8 'str'
2
3
4
5
6
7
8
9
10
11
结论分析:
- 左右两个边结构必须一样
- 右边必须是个东西
- 声明和赋值赋值不能分开,必须在一句话里
# 五、数组
ES6数组新增了4个常用方法
# 5.1 map 映射
一个对一个,得出数据映射处理后的结果,得到是一个新数组
示例一:每一项乘2操作
let arr = [12, 5, 8]
let result = arr.map(function (item) {
return item*2
})
let result2 = arr.map(item=>item*2) // 简写
console.log(result)
// [24, 10, 16]
console.log(result2)
// [24, 10, 16]
2
3
4
5
6
7
8
9
示例二:映射成绩情况
let score = [18, 86, 88, 24]
let result3 = score.map(item => item >= 60 ? '及格' : '不及格')
console.log(result3)
// [ '不及格', '及格', '及格', '不及格' ]
2
3
4
# 5.2 reduce 汇总
一堆出来一个,用于比如,算个总数,算个平均
示例一:求和运算
var arr = [1, 3, 5, 7]
var result = arr.reduce(function (tmp, item, index) {
//tmp 上次结果,item当前数,index次数1开始
return tmp + item
})
console.log(result)
// 16
2
3
4
5
6
7
示例二: 求平均值
var arr = [1, 3, 5, 7]
var result = arr.reduce(function (tmp, item, index) {
if (index != arr.length - 1) { // 不是最后一次
return tmp + item
} else {
return (tmp + item)/arr.length
}
})
console.log(result)
// 4
2
3
4
5
6
7
8
9
10
# 5.3 filter 过滤
一堆出来若干个 将计算结果为true的返回组成一个新数组
示例一:过滤出能被3整除的数
var arr = [12, 4, 8, 9]
var result = arr.filter(item => (item % 3 === 0) ? true : false)
console.log(result)
// [12, 9]
var result = arr.filter(item => item % 3 === 0)
console.log(result)
// [12, 9]
2
3
4
5
6
7
示例二:过滤出价格超过20元的商品
var arr = [
{ title: '苹果', price: 10 },
{ title: '西瓜', price: 20 },
]
var result = arr.filter(json => json.price >= 20)
console.log(result.title)
// 西瓜
2
3
4
5
6
7
# 5.4 forEach 迭代
依次遍历数组,代替数组for 循环
var arr = [12, 4, 8, 9]
var result = arr.forEach(item => console.log(item))
var result = arr.forEach((item, index)=>console.log(item, index))
2
3
5.5 额外知识点
ES2017中提出了一个数组容忍度的概念
- [1, 2, 3,] 老版数组最后不能有逗号,新的可以有
- 函数参数最后多的逗号也可以
ES2017新增了一个方法
arr.includes()
判断数组是否包含某个东西
let arr = ['a', 'b', 'c']
console.log(arr.includes(1), arr.includes('a'))
// false true
2
3
ES2017中的循环
for ... in 遍历数组 下标 key
for...of 遍历对象的 arr.keys(), arr,entries()
当时for...of遍历arr.value()是草案,之后已实现
let arr = ['a', 'b', 'c']
console.log(arr.includes(1))
for (let i in arr) {
console.log(i) // 循环的时下标 key
}
for (let i of arr) {
console.log(i) // 循环的是值 value
}
for (let i of arr.keys()) {
console.log('>'+i)
}
for (let [key, value] of arr.entries()) {
console.log('>' + key + value)
}
let json = { a: 12, b: 5, c: 7 }
for (let i in json) {
console.log(i)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 六、字符串
# 6.1 字符串模板
天大福音,简直不要太爽,告别传统字符串拼接
- 使用反引号,
${变量}
- 可以折行
示例一:传统字符串拼接
let name = 'yitian'
console.log('hello ' + name + ' !')
// hello yitian !
2
3
示例二:字符串模板
let name = 'yitian'
console.log(`hello ${name} !`)
// hello yitian !
2
3
这是最简单的例子,如果遇到字符串嵌套及折行等,传统方法写起来要发疯,字符串模板简直不要太爽
# 6.2 两个新方法
- startsWith 判断字符串开头
- endsWith 判断字符串结尾
var url = 'http://qq.com'
console.log(url.startsWith('http'))
console.log(url.endsWith('com'))
// 都是 true
2
3
4
额外知识: ES2017中新增了两个方法
padStart()/padEnd() 指定宽度,不够就补空格或指定字符
console.log('=' + 'abcd'.padStart(6, '0') + '=')
console.log('=' + 'abcd'.padEnd(6, '0') + '=')
=00abcd=
=abcd00=
2
3
4
# 七、面向对象
# 7.1 老版本
原来面向对象的写法
- 类和构造函数一样
- 属性和方法分开写的
构造函数
function User(name, pass) {
this.name = name
this.pass = pass
}
2
3
4
原型链方法
User.prototype.showName = function () {
console.log(this.name)
}
User.prototype.showPass = function () {
console.log(this.pass)
}
2
3
4
5
6
老版本继承
function VipUser(name, pass, level) {
User.call(this, name, pass)
this.level = level
}
VipUser.prototype = new User()
VipUser.prototype.constructor = VipUser
VipUser.prototype.showLevel = function () {
console.log(this.level)
}
var v1 = new VipUser('blue', '1234', 3)
v1.showName()
v1.showLevel()
2
3
4
5
6
7
8
9
10
11
12
13
# 7.2 新版本
新版面向对象,越来越接近java
- 有了 class 关键字、构造器
- class 里面直接加方法
- 继承,super 超类==父类
新版构造器
class User {
constructor(name, pass) {
this.name = name
this.pass = pass
}
showName() {
console.log(this.name)
}
showPass() {
console.log(this.pass)
}
}
var u1 = new User('able2', '111')
u1.showName()
u1.showPass()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
新版继承方式
class VipUser extends User {
constructor(name, pass, level) {
super(name, pass)
this.level = level
}
showLevel(){
console.log(this.level)
}
}
v1 = new VipUser('blue', '123', 3)
v1.showLevel()
2
3
4
5
6
7
8
9
10
11
12
# 7.3 面向对象应用
- 用于构建用户界面的 JavaScript 库
- 组件化,一个组件就是一个 class
- JSX == bable == browser.js
# 八、Json对象
# 8.1 什么是Json格式
- JavaScript Object Notation 的缩写,是一种用于数据交换的文本格式
- JSON 是 JS对象 的严格子集
- JSON 的标准写法
- 只能用双引号
- 所有的key都必须用双引号包起来
# 8.2 Json处理方法
JSON 对象是 JavaScript 的原生对象,用来处理 JSON 格式数据,有两个静态方法
JSON.parse(string) :
接受一个JSON 字符串并将其转换成一个 JavaScript 对象。
var json = {a: 12, b: 5}
var str = 'hi,' + JSON.stringify(json)
var url = 'http://www.xx.com/' + encodeURIComponent(JSON.stringify(json))
console.log(str)
// hi,{"a":12,"b":5}
console.log(url)
// http://www.xx.com/%7B%22a%22%3A12%2C%22b%22%3A5%7D
2
3
4
5
6
7
JSON.stringify(obj) :
接受一个 JavaScript 对象并将其转换为一个 JSON 字符串。
var str = '{"a": 12, "b": 4, "c": "abc"}'
var json = JSON.parse(str)
console.log(json)
// { a: 12, b: 4, c: 'abc' }
2
3
4
# 8.3 什么是对象
是 JavaScript 语言的核心概念,也是最重要的数据类型
对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合
对象的所有键名都是字符串, 所以加不加引号都可以
如果键名是数值,会被自动转为字符串
对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型
如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用
in 运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值
for...in循环用来遍历一个对象的全部属性
对象简写:
- key-value 一样时可以简写
- 里面函数可以简写, 去掉
:function
let a = 5, b = 12
// 传统写法
let json = {a: a,b: b, c: 18}
let fnObj = {
show: function(){
...
}
}
// 简写写法
let json = {a, b, c: 18}
let fnObj = {
show(){
...
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 九、异步操作优化
# 9.1 异步和同步
- 异步,操作之间没有关系,同时执行多个操作, 代码复杂
- 同步,同时只能做一件事,代码简单
# 9.2 Promise对象
优点:
- 用同步的方式来书写异步代码
- Promise 让异步操作写起来,像在写同步操作的流程,不必一层层地嵌套回调函数,有效避免了回调地狱
- 改善了可读性,对于多层嵌套的回调函数很方便
- 充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口
使用方法:
- 接受一个回调函数f1作为参数,f1里面是异步操作的代码
- 返回的p1就是一个 Promise 实例
- 所有异步任务都返回一个 Promise 实例
- Promise 实例有一个then方法,用来指定下一步的回调函数
function f1(resolve, reject) {
// 异步代码...
}
var p1 = new Promise(f1);
p1.then(f2); // f1的异步操作执行完成,就会执行f2。
2
3
4
5
写法优化:
Promise 使得异步流程可以写成同步流程
// 传统写法,经典回调地狱
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// ...
});
});
});
});
// Promise 的写法
(new Promise(step1))
.then(step2)
.then(step3)
.then(step4);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 9.3 Promise新增2个操作方法
**Promise.all(promiseArray):**全部成功
当全部执行完才会执行then
,其中任何一项出错执行catch
- 将多个Promise对象实例包装,生成并返回一个新的Promise实例
- promise数组中所有的promise实例都变为resolve的时候,该方法才会返回
- 并将所有结果传递results数组中
- promise数组中任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的promise对象
var p1 = Promise.resolve(1),
p2 = Promise.resolve(2),
p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then((results)=>{
console.log(results); // [1, 2, 3]
}).catch((err)=>{
...
});
2
3
4
5
6
7
8
Promise.race(promiseArray): 赛跑
返回执行最快的异步某个操作的状态及结果
- Promse.race就是赛跑的意思
- 哪个结果获得的快,就返回那个结果
- 不管结果本身是成功状态还是失败状态
额外新增:
在ES2020新增了另外两个优秀的方法
Promise.allSettled(promiseArray):只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束
Promise.any(promiseArray):任何一个成功即为成功,所有失败才为失败
# 9.4 generator-认识生成器函数
普通函数,一路到底
- generator函数,中间可以停,到哪停呢,用 yield 配合,交出执行权
- yield 有 放弃、退让、退位的意思
- 需要调用next()方法启动执行,需要遇到 yield 停, 踹一脚走一步
- generator函数前面加一个
*
两边可以有空格,或靠近函数或function
- 背后实际生成多个小函数,实现走走停停
function show() {
console.log('a')
console.log('b')
}
show() // 普通函数
function *show2() {
console.log('1')
yield
console.log('2')
}
let genObj = show2()
genObj.next() // 1
genObj.next() // 2
genObj.next() // 最后了,没有结果
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 9.5 generator-yield
yield
既可传参,又可以返回,第一个next()
传参无效,只用来启动
如果函数前漏掉 *
- 就是普通函数
- 如果有
yield
会报错,ReferenceError: yield is not defined
- yield 只能在Generator函数内部使用
function * show() {
console.log('1')
var a = yield
console.log('2')
console.log(a)
}
// yield 传参
var gen = show()
gen.next() // 1
gen.next() // 2 和 undefined 因为没有传参,yield没有返回值
var gen = show()
gen.next(10) // 1 第一次执行到yield,但没有执行赋值
gen.next(20) // 2 和 20
function* show2() {
console.log('1')
yield 10
console.log('2')
}
// yield 返回
var gen = show2()
var res1 = gen.next()
console.log(res1) // { value: 10, done: false }
var res2 = gen.next()
console.log(res2)
// { value: undefined, done: true } 最后的value需要return返回
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 9.6 generator-实例
- Promise 适合一次读一组
- generator 适合逻辑性的
// 带逻辑-generator
runner(function * () {
let userData = yield $.ajax({url: 'getUserData'})
if (userData.type == 'VIP') {
let items = yield $.ajax({url: 'getVIPItems'})
} else {
let items = yield $.ajax({url: 'getItems'})
}
})
// yield 实例,用同步方式写异步
server.use(function * () {
let data = yield db.query(`select * from user_table`)
this.body = data
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 9.7 async await
- 和 generator yield 类似
- generator 不可以写成箭头函数, async 可以
async function show() {
console.log(1)
await
console.log(2)
}
2
3
4
5
- 一、ES6背景知识
- 1.1 ECMAScript 和 JavaScript
- 1.2 重要历史版本
- 1.3 ES6兼容性
- 二、变量 let 和 常量 const
- 2.1 var 的问题
- 2.2 let 和 const
- 2.3 块级作用域举例
- 三、箭头函数
- 3.1 箭头函数的简写
- 3.2 箭头函数注意点
- 四、扩展和解构赋值
- 4.1 参数扩展/展开
- 4.2 解构赋值
- 五、数组
- 5.1 map 映射
- 5.2 reduce 汇总
- 5.3 filter 过滤
- 5.4 forEach 迭代
- 六、字符串
- 6.1 字符串模板
- 6.2 两个新方法
- 七、面向对象
- 7.1 老版本
- 7.2 新版本
- 7.3 面向对象应用
- 八、Json对象
- 8.1 什么是Json格式
- 8.2 Json处理方法
- 8.3 什么是对象
- 九、异步操作优化
- 9.1 异步和同步
- 9.2 Promise对象
- 9.3 Promise新增2个操作方法
- 9.4 generator-认识生成器函数
- 9.5 generator-yield
- 9.6 generator-实例
- 9.7 async await