视频地址: link
1.let
和const
的使用及注意点
let
/const
定义的变量并没有挂载到window上,故而不能通过window点出来
1.0var
存在的问题
- var定义的变量就直接挂载到window上了
for (var i = 0; i < 10; i++) {
//小括号里面的i是一个全局变量 通过var定义的变量只有函数内部的局部变量和全局变量之分,for循环if判断中定义的都是全局变量
//js的执行逻辑
//(1)在js主程序(单线程)上的同步任务形成了一个主任务执行栈
//(2)主线程之外还存在一个任务队列,这个队列存在一些按时间顺序存放的事件,如鼠标点击、计时触发等,主线程中每出现一个异步任务,任务队列就会增加一个异步任务的事件
//(3)一般执行栈中的同步任务执行完毕,系统就会读取任务队列,看看哪些事件是可以执行的,一旦可以执行将进入执行栈开始执行
//(4)不断重复以上动作
//如果真的用var,这里面就不能存在不进行特别处理的异步操作,因为for(这里面是直接在主任务执行栈上操作的){
//这里面的异步操作不在主程序栈上执行操作,需要等到主程序都执行完再执行}
(function (i) {
//这样的特殊处理
setTimeout(() => {
console.log(i);
}, 1000 * i);
})(i);
};
console.log(i);//10由于定义的是全局变量,导致污染了全局变量
if (true) {
var a = 12;//相当于定义了一个全局变量
}
console.log(a)//12
1.1let
的使用及注意点
- 注意点汇总
{
let 定义的变量只能在这个块级作用域中使用,外部是不能调用的
let 定义的变量没有预解析, 不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!
在同一个块级作用域中不能重复的定义变量
for循环,小括号中的是父级作用域而花括号中的是子集作用域
}
let就是相当于之前的var只不过每一个let都有自己的块级作用域
1.1.1let
定义的变量只能在这个块级作用域中使用,外部是不能调用的
for (let i = 0; i < 10; i++) {
console.log(i)//正常打印
}
// console.log(i)//报错:找不到i
if (true) {
let a = 6;//通过let定义的变量只能在当前的代码块中调用
console.log(a)//6
}
console.log(a)//报错找不到a
1.1.2let
定义的变量没有预解析,不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!
let a = 12;
function func() {
//只要在当前的块级作用域中通过let定义了变量,那么一定会使用这个变量
console.log(a);//报错 原因没有预解析这么一说了
let a = 2;
}
func();
1.1.3let
在同一个块级作用域中不能重复的定义变量
var a = 12;
var a = 5;
console.log(a)//5后面定义的a会覆盖前面定义的a
let a = 1;
let a = 2;// 在同一个块级作用域中不能重复的定义变量
console.log(a)//报错 Uncaught SyntaxError: Identifier 'a' has already been declared//a已经声明了
1.1.4 for
循环,小括号中的是父级作用域而花括号中的是子集作用域
for (let i = 0; i < 3; i++) {
//小括号中的是父级作用域而花括号中是子集作用域
// console.log(i)//0/1/2;
let i = 'xbc';
console.log(i)//没有报错并且输出xbc/xbc/xbc
}
{
//父级作用域父级作用域是访问不到子集作用域中的变量的
let a = 12;
{
//子集作用域
let a = 5;
console.log('子集作用域:', a)//5
}
console.log('父级作用域:', a)//12
}
1.3const
的使用及注意点
- 注意点汇总
{
const 定义的变量只能在这个块级作用域中使用,外部是不能调用的
const定义的变量没有预解析,不存在变量提升,在代码块中,只要let定义的变量,在之前调用,都是会报错的!先定义后使用!
在同一个块级作用域中不能重复的定义变量
for循环,小括号中的是父级作用域而花括号中的是子集作用域
}
每一个const都有自己的块级作用域
1.3.1const
的特性和let是一样的不同的是const
定义好了就不能改变了
const a = 16;
a = 18;
console.log(a)//报错:分配给常量变量
1.3.2const
定义完变量必须有值,不能先声明后赋值
const a;
a = 16;
console.log(a)//报错:声明中缺少初始值设定
1.3.3通过const
指定的只能是普通的,不能是引用机制的例如数组
const arr = ['apple', 'banana'];
arr.push('orange');//对象是引用机制,所以能修改缓存,要想实现彻底的常量可以用Object.freeze(对象)方法
console.log(arr);//["apple", "banana", "orange"]
const arr =Object.freeze(['apple,banana']);//冻住数组可以,但是也只能限制push/unshift/shift/pop等方法,如果数组里面放置的是对象,通过数组[index].key的方式修改,也是不行的
arr.push('orange');
console.log(arr)//报错Uncaught TypeError: Cannot add property 1, object is not extensible
2.解构赋值
2.1解构数组
2.1.1基本使用-左右两边的数据结构要一致
let [a, b, c] = [1, 2, 3];
console.log(a,b,c)//1 2 3
let [a, [b, c]] = [12, [5, 6]];
console.log(a, b, c);//12/5/6
let [a, ...b] = [1, 2, 3];
console.log(a,b)//1 (2) [2, 3]
2.1.2设置默认值
let [a, b, c='暂无数据'] = [1, 2];
console.log(a,b,c)//1,2,暂无数据
2.1.3应用
交换a,b的值
let a = 12;
let b = 18;
[b, a] = [a, b];
console.log(a,b)//18,12
2.2解构对象
2.2.1基本使用-左右两边的数据结构要一致
let {
age, name, job } = {
name: 'xbc', age: 26, job: 'web开发' };
console.log(age, name, job)//26 "xbc" "web开发"
2.2.2设置别名
let {
name: name1, age: age2, job: job3 } = {
name: 'xbc', age: 26, job: 'web开发' };
console.log(name1)//xbc
console.log(age2)//26
console.log(job3)//web开发
2.2.3设置默认值
let {
age, name, job, skill = 'cook' } = {
name: 'xbc', age: 26, job: 'web开发' };
console.log(age, name, job, skill)//26 "xbc" "web开发" "cook"
2.2.4解构函数的返回值也可以解构原型上的任意方法
function getPos() {
return {
left: 10,
right: 20,
bottom: 30,
top: 40
}
}
let {
left, right, top, bottom:b } = getPos();
console.log('left',left)//10
console.log('right',right)//20
console.log('top',top)//40
console.log('bottom',b )//30
2.2.5函数传参
function func({
name, age, sex = '男' }) {
console.log(name, 'name')//xbc
console.log(age, 'age')//26
console.log(sex, 'sex')//男
}
func({
age: 26, name: 'xbc' });//最少传一个空对象
function func({
name = 'xbc', age = 26, sex = '男' } = {
}) {
console.log(name, 'name')//xbc
console.log(age, 'age')//26
console.log(sex, 'sex')//男
}
func();
3.字符串模板
- 使用方式:
${变量的名称}
优点:可以随意的换行
3.1基本使用
let name = 'xbc';
let age = 26;
let str = `这个人是${
name}年龄是${
age}`;
console.log(str)//这个人是xbc年龄是26
let data = [
{
title: '新闻', read: 1000 },
{
title: '科技创新助力政府推动数字生活 数字中国建设峰会', read: 666 },
{
title: '新闻1', read: 888 },
{
title: '中国经济发展韧性十足', read: 1666 },
{
title: '中国外交部:加征关税解决不了任何问题', read: 1888 },
{
title: '看!你的户口、土地、收入将发生这些变化', read: 999 }
]
let ul = document.querySelector('.ul');
for (let i = 0; i < data.length; i++) {
let li = document.createElement("li")
li.innerHTML = `
<span>${
data[i].title}</span>
<span>${
data[i].read}</span>
<a href="javascript:;">详情</a>
`
ul.appendChild(li)
}
3.2字符串新加的一些方法
3.2.1字符串查找片段str.includes
- 使用方式
['需要判断的字符串'].includes('判断是否包含的片段')
- 返回值:布尔
let str = 'apple banbana pear';
let index = str.indexOf('banbana');//返回的是索引的位置
if (index !== -1) {
console.log('字符串中存在查找的值')
} else {
console.log('字符串中没有查找的值')
}
let bool = str.includes('pear');
console.log(bool)//字符串中包含不包含需要查找的片段找到返回true找不到返回false精确查找需用正则表达式
3.2.2字符串是不是以某一个字符或者字符片段开头
- 使用方式
['需要判断的字符串'].startsWith('判断是否是根据这个字符串开头的字符串')
- 返回值:布尔
let str = 'https://www.baidu.com';
let bool = str.startsWith('http');
console.log(bool)//返回true或者false
3.2.3字符串是不是以某一个字符或者字符片段结尾
- 使用方式
['需要判断的字符串'].startsWith('判断是否是根据这个字符串结尾的字符串')
- 返回值:布尔
let str = 'xbc.jpg';
let bool = str.endsWith('jpg');
console.log(bool)//返回true或者false
3.2.4重复字符串
- 使用方式
str.repeat('需要重复的次数Number类型')
- 返回值:一个新的字符串
let str='牧马人';
let newStr=str.repeat(3);//括号里面规定重复多少次
console.log(newStr);//返回一个新的字符串
3.2.5字符串填充-前填充
['参考字符串'].padStart('填充完毕之后的字符串的长度','需要填充的字符串要放在参考字符串的前面')
- 返回值:一个新的字符串
let name = '三';
let surname = '张'
let newName = name.padStart(surname.length + name.length, surname);
console.log(newName)//张三
3.2.6字符串填充-后填充
['参考字符串'].padStart('填充完毕之后的字符串的长度','需要填充的字符串要放在参考字符串的后面')
- 返回值:一个新的字符串
let surname = '李';
let name='四'
let newName = surname.padEnd(surname.length+name.length,name);
console.log(newName)//李四
4.函数
4.1函数的默认参数
function func(a = '暂无数据。。。', b = '暂无数据。。。') {
//函数的默认值
console.log(a, b)//欢迎 暂无数据。。。
}
func('欢迎');
function position({
x = 0, y = 0 } = {
}) {
//利用解构赋值,给定默认值
console.log(x, y)//10 20
}
position({
x: 10, y: 20 });
4.2函数的参数声明问题
- 在函数中函数的参数默认已经被定义了,不能在当前的块中继续使用
let/count
声明已经在小括号中声明的变量了,和for不一样,函数没有子集作用域一说。
function show(a = 20) {
let a = 101;
console.log(a);//报错,a已经被定义了。。。
};
show();
4.3箭头函数
4.3.1基本使用
function show(a, b) {
return a + b;
}
console.log(show(12, 5));//17
// ()=>{
//完整的箭头函数格式
// }
let show1 = (a, b) => {
return a + b
}
console.log(show1(5, 6));//11
let show2 = (a, b) => a + b;//默认就是return
console.log(show2(10, 20));//30
4.3.2箭头函数中this
的注意点:定义函数所在对象,不再是调用时所在的对象
- 使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了!
let json = {
id: 1,
show: function () {
//这的this就是指向调用者的了
// setTimeout(function () {
// console.log(this);//{window: Window, self: Window, document: document, name: "", location: Location, …}
// }, 1000);
setTimeout(() => {
//使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了,这里没有this,往上找
console.log(this);//{id: 1, show: ƒ}
}, 1000);
},
show1: () => {
//这里没有this往上找
setTimeout(() => {
//使用了箭头函数,当前的this指向当前的对象,this指向的是定义函数所在的对象,而不是运行函数所在的对象了,这里没有this,往上找
console.log(this);//{window: Window, self: Window, document: document, name: "", location: Location, …}
}, 1000);
}
};
json.show();//这里面就是json
json.show1();//由于定义show1的是箭头函数,里面的定时器也是箭头函数,所以,他们都没有自己的this,只能往上找,最终找到window,即使通过call/apply都不能更改this的指向了
4.3.3箭头函数中是没有argurments
的用…
即可
let show = (...arr) => {
// console.log(arguments);//没有arguement
console.log(arr);//[10, 20, 30]
};
show(10, 20, 30);
4.3.4箭头函数中不能当成构造函数
function Person(){
this.name='张三'
}
let p=new Person();
console.log(p);//Person {name: "张三"}
let show=()=>{
this.name='李四'
}
let s=new show();
console.log(s);//show is not a constructor
5.扩展运算符
5.1扩展运算符之数组相关操作
5.1.1展开数组
let arr=['apple', 'banana', 'orange']
console.log(...arr)//apple banana orange
5.1.2复制数组
- 复制数组不是复制引用
let arr = [1, 2, 3];
let newArr = [...arr];
newArr.push(4);
console.log(arr, newArr);//[1, 2, 3],[1, 2, 3, 4]
5.1.3函数传参
5.1.3.1函数传参
function show() {
let arr=Array.prototype.slice.call(arguments);
return arr.sort(function (a, b) {
return b - a
})
};
console.log(show(1, -2, 33, -4, 35, 86))//[86, 35, 33, 1, -2, -4]
//扩展运算符,reset剩余运算符
//...[1,2,3,4,5,6]==>1,2,3,4,5,6;展开
//...1,2,3,4,5,6==>[1,2,3,4,5,6];收起
function show(...arr) {
//用在函数的形参上
return arr.sort(function (a, b) {
return b - a
});
}
let arr = show(1, -2, 33, -4, 35, 86);
console.log(arr);//[86, 35, 33, 1, -2, -4]
5.1.3.2利用扩展运算符将函数的参数提前展开,便于函数调用
function func(a, b, c) {
console.log(a, b, c)
}
func(...[1, 2, 6]);//用在函数的实参上
5.1.3.3剩余运算符必须放到最后,不能放别处
function func(a,...b) {
console.log(a, b)//1,[2, 6]
}
func(...[1, 2, 6]);
5.2扩展运算符之对象相关操作
5.2.1基本使用
let {
x, y, ...z } = {
x: 1, y: 2, a: 10, b: 20 };
console.log(x,y,z)//1 2 {a: 10, b: 20}
let json = {
name: '张三', age: 26, sex: '男' };
let newJson = {
...json };
newJson.skill = 'web开发'
console.log(newJson)//{name: "张三", age: 26, sex: "男", skill: "web开发"}
console.log(json)//{name: "张三", age: 26, sex: "男"}
6.数组循环
6.0数组的新增方法
6.0.1Array.form:将伪数组转成数组或者将str,json转成数组
function show() {
return Array.from(arguments).sort(function (a, b) {
return a - b
})
}
console.log(show(1, -2, 33, -4, 35, 86));//[-4, -2, 1, 33, 35, 86]
let str = 'xbc';
let arr = Array.from(str)
console.log(arr)// ["x", "b", "c"]
let json = {
0: 'xbc', 1: 24 };
json.length = 2;//没有length的需要添加一个length才能正常转化
let arr = Array.from(json)
console.log(arr)// ["xbc",24]
6.0.2Array.of:将一组值转换成数组
let arr = Array.of('apple', 'banbana', 'orange');//类似于函数传参
console.log(arr)// ["apple", "banbana", "orange"]
6.0.3Array.fill:填充数组
let arr = new Array(10);//设置数组的长度
arr.fill('默认值');//规定数组的填充内容
console.log(arr)//["默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值", "默认值"]
6.0.4Array.includes:查找数组中是否包含某个字符片段
let arr = ['apple', 'banana', 'orange'];
let index = arr.indexOf('banana');
let bool = arr.includes('banana');//数组中是否包含需要查找的字符串
console.log(index)//1
console.log(bool)//true
6.1for of循环
6.1.1for of循环index
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
for (const index of arr.keys()) {
console.log(index);//0 1 2 3 4 5 6 7 8 9
}
6.1.2for of循环item
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
for (const item of arr.values()) {
console.log(item);
//{name: "张三", num: 181, bool: false}
//{name: "张三", num: 182, bool: false}
//{name: "张三", num: 183, bool: false}
//{name: "张三", num: 186, bool: false}
//{name: "张三", num: 185, bool: false}
//{name: "张三", num: 186, bool: false}
//{name: "张三", num: 187, bool: false}
//{name: "张三", num: 188, bool: false}
//{name: "张三", num: 189, bool: false}
//{name: "张三", num: 190, bool: false}
}
6.1.3for of循环key/item
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
for (const [key,item] of arr.entries()) {
console.log(key,item);
//0 {name: "张三", num: 181, bool: false}
//1 {name: "张三", num: 182, bool: false}
//2 {name: "张三", num: 183, bool: false}
//3 {name: "张三", num: 186, bool: false}
//4 {name: "张三", num: 185, bool: false}
//5 {name: "张三", num: 186, bool: false}
//6 {name: "张三", num: 187, bool: false}
//7 {name: "张三", num: 188, bool: false}
//8 {name: "张三", num: 189, bool: false}
//9 {name: "张三", num: 190, bool: false}
}
6.2forEach
- forEach方法里操作对象生效,想要操作里面的基本数据类型,就用arr[i]的形式直接操作数组。
- arr.forEach/arr.map/arr.filter/arr.some/arr.every都能接受两个参数其一是回调函数其二是this(希望this指向谁)
- 注意点:要想改变this的指向,回调函数必须是非箭头函数形式
6.2.1基本使用
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
arr.forEach(function (item, index) {
//非箭头函数可以修改this指向
console.log(item, index, this);
//{name: "张三", num: 181, bool: false} 0 Number {996}
//{name: "张三", num: 182, bool: false} 0 Number {996}
//{name: "张三", num: 183, bool: false} 0 Number {996}
//{name: "张三", num: 186, bool: false} 0 Number {996}
//{name: "张三", num: 186, bool: false} 0 Number {996}
//{name: "张三", num: 187, bool: false} 0 Number {996}
//{name: "张三", num: 188, bool: false} 0 Number {996}
//{name: "张三", num: 189, bool: false} 0 Number {996}
//{name: "张三", num: 190, bool: false} 0 Number {996}
}, 996)
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
arr.forEach((item, index) => {
//箭头函数无法修改this指向,因为箭头函数没有this,因为函数是在window中定义的,所以 this就是window
console.log(item, index, this);
//{name: "张三", num: 181, bool: false} 0 window
//{name: "张三", num: 182, bool: false} 0 window
//{name: "张三", num: 183, bool: false} 0 window
//{name: "张三", num: 186, bool: false} 0 window
//{name: "张三", num: 186, bool: false} 0 window
//{name: "张三", num: 187, bool: false} 0 window
//{name: "张三", num: 188, bool: false} 0 window
//{name: "张三", num: 189, bool: false} 0 window
//{name: "张三", num: 190, bool: false} 0 window
}, 996)
6.2.2修改item
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
arr.forEach((item, index) => {
arr[index].addKey1 = item.name + item.num;
arr[index].addKey2 = 'addKey2';
});
console.log(arr);
//[{name: "张三", num: 181, bool: false, addKey1: "张三181", addKey2: "addKey2"}
//{name: "张三", num: 182, bool: false, addKey1: "张三182", addKey2: "addKey2"}
//{name: "张三", num: 183, bool: false, addKey1: "张三183", addKey2: "addKey2"}
//{name: "张三", num: 186, bool: false, addKey1: "张三186", addKey2: "addKey2"}
//{name: "张三", num: 185, bool: false, addKey1: "张三185", addKey2: "addKey2"}
//{name: "张三", num: 186, bool: false, addKey1: "张三186", addKey2: "addKey2"}
//{name: "张三", num: 187, bool: false, addKey1: "张三187", addKey2: "addKey2"}
//{name: "张三", num: 188, bool: false, addKey1: "张三188", addKey2: "addKey2"}
//{name: "张三", num: 189, bool: false, addKey1: "张三189", addKey2: "addKey2"}
//{name: "张三", num: 190, bool: false, addKey1: "张三190", addKey2: "addKey2"}]
6.3map
6.3.1使用方法一
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let newArr = arr.map((item, index) => {
return {
name1: item.name,
height: item.num + 'cm'
}
});
console.log(newArr);
//[{name1: "张三", height: "181cm"}
//{name1: "张三", height: "182cm"}
//{name1: "张三", height: "183cm"}
//{name1: "张三", height: "186cm"}
//{name1: "张三", height: "185cm"}
//{name1: "张三", height: "186cm"}
//{name1: "张三", height: "187cm"}
//{name1: "张三", height: "188cm"}
//{name1: "张三", height: "189cm"}
//{name1: "张三", height: "190cm"}]
6.3.2使用方法二
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let newArr = arr.map((item, index) => {
item.key1 = 'key' + index;
item.key2 = 'key' + item.num;
return item;
});
console.log(newArr);
//[{name: "张三", num: 181, bool: false, key1: "key0", key2: "key181"}
//{name: "张三", num: 182, bool: false, key1: "key1", key2: "key182"}
//{name: "张三", num: 183, bool: false, key1: "key2", key2: "key183"}
//{name: "张三", num: 186, bool: false, key1: "key3", key2: "key186"}
//{name: "张三", num: 185, bool: false, key1: "key4", key2: "key185"}
//{name: "张三", num: 186, bool: false, key1: "key5", key2: "key186"}
//{name: "张三", num: 187, bool: false, key1: "key6", key2: "key187"}
//{name: "张三", num: 188, bool: false, key1: "key7", key2: "key188"}
//{name: "张三", num: 189, bool: false, key1: "key8", key2: "key189"}
//{name: "张三", num: 190, bool: false, key1: "key9", key2: "key190"}]
6.4filter
- 将符合条件的元素过滤出来返回一个新的数组如果回调函数返回是true就留下来
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let newArr = arr.filter((item, index) => {
return item.num > 185
});
console.log(newArr);
//[{name: "张三", num: 186, bool: false}
//{name: "张三", num: 186, bool: false}
//{name: "张三", num: 187, bool: false}
//{name: "张三", num: 188, bool: false}
//{name: "张三", num: 189, bool: false}
//{name: "张三", num: 190, bool: false}]
6.5some
- 类似于查找,数组中的某一个元素符合条件就返回true
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let bool = arr.some((item, index) => {
return item.num > 185
});
console.log(bool);//true
6.6every
- 数组中的所有元素都必须符合条件才返回true
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let bool = arr.every((item, index) => {
return item.num > 185
});
console.log(bool);//false
6.7reduce
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let count = arr.reduce((prev, curr) => {
console.log(curr);//{ name: '张三', num: 181, bool: false }开始
return prev + curr.num
}, 0);
console.log(count);//1857
6.8reduceRight
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let count = arr.reduceRight((prev, curr) => {
console.log(curr);//{ name: '张三', num: 190, bool: false }开始
return prev + curr.num
}, 0);
console.log(count);//1857
6.9find
- 查找数组中符合条件的第一个元素并返回
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let findObj= arr.find((item, index) => {
return item.num > 185;
});
console.log(findObj);//{name: "张三", num: 186, bool: false}
6.10findIndex
- 查找数组中符合条件的第一个元素并返回其对应的索引值
let arr = [
{
name: '张三', num: 181, bool: false },
{
name: '张三', num: 182, bool: false },
{
name: '张三', num: 183, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 185, bool: false },
{
name: '张三', num: 186, bool: false },
{
name: '张三', num: 187, bool: false },
{
name: '张三', num: 188, bool: false },
{
name: '张三', num: 189, bool: false },
{
name: '张三', num: 190, bool: false }
]
let index = arr.findIndex((item, index) => {
return item.num > 185;
});
console.log(index);//3
7.对象
7.1对象的简洁语法
let name = '张三';
let age = 18;
let json = {
name,//name:name
age,//age:age
skill: function () {
console.log(this);//{name: "张三", age: 18, skill: ƒ}
},
skill1: () => {
console.log(this);//window
},
skill2() {
//{name: "张三", age: 18, skill: ƒ, skill1: ƒ, skill2: ƒ}
console.log(this);
}
};
json.skill();
json.skill1();
json.skill2();
7.2for of
循环对象
7.2.1for of
循环key
let json = {
name: '张三',
age: 16,
sex: '男'
}
for (const key of Object.keys(json)) {
console.log(key);// name age sex
}
7.2.2for of
循环item
let json = {
name: '张三',
age: 16,
sex: '男'
}
for (const item of Object.values(json)) {
console.log(item);// 张三 16 男
}
7.2.3for of
循环key item
let json = {
name: '张三',
age: 16,
sex: '男'
}
for (const [key, value] of Object.entries(json)) {
console.log(key, value);// name 张三 age 16 sex 男
}
7.3对象的简洁语法传参
let x = 10;
let y = 20;
function sum({
x, y }) {
return x + y
};
console.log(sum({
x, y }))//30
7.4Object.is
判断两个一模一样的东西是不是相等的
let bool = Object.is('a', 'a');
console.log(bool)//true判断两个一模一样的东西是不是相等
let bool1 = Object.is(+0, -0);
console.log(bool1)//false判断两个一模一样的东西是不是相等
let bool2 = Object.is(NaN, NaN);
console.log(bool2)//true判断两个一模一样的东西是不是相等
7.5Object.assign
(目标对象,对象1,对象2……)用途:复制对象,合并参数
let peopleInformation = {
name: '张三',
age: 24,
sex: '男'
};
let skills = {
skill1: 'web开发',
skill2: 'cooking'
}
Object.assign(peopleInformation, skills);
console.log(peopleInformation)//name: "张三", age: 24, sex: "男", skill1: "web开发", skill2: "cooking"}
let defaultInformation = {
name: '用户',
age: 18,
sex: '男'
}
let userInformation = {
name: '张三',
age: 26
};
let json = {
}
Object.assign(json, defaultInformation, userInformation);
console.log(json)//{name: "张三", age: 26, sex: "男"}
8.Promise
- 作用:解决异步回调问题
//传统方式,大部分用回调函数,事件
ajax(url,{//获取token
ajax(url,()=>{//获取用户信息
ajax(url,()=>{
//获取用户相关的新闻
})
})
});
8.1promise
语法
8.1.1基础语法
new Promise(function(resolve,reject){
//返回一个promis对象
//resolve:成功时候调用
//reject:失败的时候调用
});
8.1.2例一
let a = 10;
let json = new Promise(function (resolve, reject) {
if (a == 10) {
resolve('success')
} else {
reject('error')
}
});
json.then(res => {
console.log(res);//如果是a=10返回成功的结果
}, err => {
console.log(err)//如果是a!=10返回的是失败的结果
})
8.1.2例二
let name = '张三'
let promiseObject = new Promise(function (resolve, reject) {
if (name == '张三') {
resolve('张三')
} else {
reject('其他人')
}
});
promiseObject.then(success => {
//then的返回值还是promise对象
console.log(success)
}).catch(error => {
//这个就等同于成功和失败都写在.then中的错误返回的函数
console.log(error)
})
8.1.3综合实例
let status = 1;
let userLogin = (resolve, reject) => {
setTimeout(() => {
if (status == 1) {
resolve({
data: '登录成功', msg: 'xxx', token: 'asldkfjlskdfjlk' })
} else {
reject('登录失败')
}
}, 1000);
}
let userMsg = (resolve, reject) => {
setTimeout(() => {
if (status == 1) {
resolve({
data: '获取用户信息成功', msg: 'xxx', token: 'asldkfjlskdfjlk' })
} else {
reject('登录失败')
}
}, 1000);
}
new Promise(userLogin).then(res => {
console.log(res);
return new Promise(userMsg)
}).then(res => {
console.log(res);
})
8.2Promise.resolve
(‘需要处理的元素’)//将括号内的元素处理成一个resolve
状态的promise
对象(成功状态)
Promise.resolve('aaa').then(res => {
console.log(res)//aaa
});
new Promise(function (resolve) {
//这个等价于上面那个写的方式
resolve('aaa')
}).then(res => {
console.log(res)//aaa
});
8.3Promise.reject
(‘需要处理的元素’)//将括号内的元素处理成一个reject
状态的promise
对象(失败状态)
Promise.reject('bbb').catch(err => {
console.log(err)//bbb
})
new Promise(function (reject) {
//这个等价于上面那个写的方式
reject('bbb')
}).catch(res => {
console.log(res)//bbb
});
8.4Promise.all
([‘reslove对象1’,‘reslove对象2’, ‘reslove对象3’])
let a = Promise.resolve('aaa');
let b = Promise.resolve('bbb');
let c = Promise.resolve('ccc');
Promise.all([a, b, c]).then(arr => {
//必须确保所有的promise都是resolve状态
console.log(arr)//["aaa", "bbb", "ccc"]
let [res1, res2, res3] = arr;
console.log(res1, res2, res3)//aaa bbb ccc
});
8.5Promise. race
([‘reslove对象1’,‘reslove对象2’, ‘reslove对象3’])
let a = Promise.resolve('aaa');
let b = Promise.resolve('bbb');
let c = Promise.reject('ccc');
Promise.race([a, b, c]).then(arr => {
//只要有一个成功就返回
console.log(arr)//aaa
});
9.模块化
- 注意点:
export
import
都需要放到服务器的环境中 - 如何定义模块?
export
- 如何使用模块?
import
9.1import
特点
9.1.1通过import
引入的js模块即可以是相对路径也可以是绝对路径
9.1.1.1import
引入绝对路径
import 'https://cdn.bootcdn.net/ajax/libs/jquery/1.8.3/jquery.js';
9.1.1.2import
引入相对路径
import '../../module/index.js'//相对路径这么做相当于引入了一个js文件
9.1.2import
无论导入多少次,只会导入一次
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
import '../js/func.js';
9.1.3导出去的模块,如果里面有内容更改,引入的时候也会更改,即使用定时器
let name = '张三';
export const age = 26;
setTimeout(() => {
name='李四'
}, 2000);
export {
name
}
import {
name} from '../js/func.js';
setTimeout(() => {
console.log(name);
}, 2000);
9.1.4import
有提升效果
new mod.People().showName('工作');
show();
sum();
console.log(a);
console.log(b);
import mod,{
show,sum,a,b} from '../../model/index.js'
9.1.5import
类似于node
里面的require
,可以动态引入,默认import
语法不能写到if
或者for
中。
if(true){
import ('https://cdn.bootcdn.net/ajax/libs/jquery/1.8.3/jquery.js').then(res=>{
console.log($);
})
}
let js='index-1.js'
if(js=='index-1.js'){
import('../../model/index-1.js').then(res=>{
console.log(res)
})
}else{
import('../../model/index-2.js').then(res=>{
console.log(res)
})
}
9.1.6按需加载 可以写在if中 路径 import的返回值是要给promise对象,可以用then
Promise.all([
import('../../model/index-1.js'),
import('../../model/index-2.js')
]).then(([index1,index2])=>{
console.log(index1,index2)
})
9.2async await
async function main(){
const mod1=await import('../../model/index-1.js');
const mod2=await import('../../model/index-2.js');
console.log(mod1,mod2);
const [m1,m2]= await Promise.all([
import('../../model/index-1.js'),
import('../../model/index-2.js')
]);
console.log(m1,m2);
}
main();
9.3设置别名
9.3.1在需要导出js文件中设置别名
9.3.1.1导出js文件
const userName = '肖宝成';
let age = 24;
const sex = '男'
function func(){
console.log('func')
}
export {
userName as aaa,
age as bbb,
func as ccc,
sex as ddd
}
9.3.1.2引入js文件
import {
aaa,bbb,ccc,ddd } from '../../model/index-1.js'//相对路径
console.log(aaa);//肖宝成
console.log(bbb);//24
ccc();//func
console.log(ddd)//男
9.3.2在需要引入的js文件中设置别名
9.3.2.1导出js文件
const userName = '肖宝成';
let age = 24;
const sex = '男'
function func(){
console.log('func')
}
export {
userName,
age,
func,
sex
}
9.3.2.2引入js文件
import {
userName as aaa,age as bbb,func as ccc,sex as ddd } from
'../../model/index-1.js'//相对路径
console.log(aaa);//肖宝成
console.log(bbb);//24
ccc();//func
console.log(ddd)//男
import * as modelName from '../../model/index-1.js'//相对路径
console.log(modelName)
//age: 24
//func: ƒ func()
//sex: "男"
//userName: "肖宝成"
console.log(modelName.userName);//肖宝成
console.log(modelName.age);//24
modelName.func();//func
console.log(modelName.sex)//男
9.4事例操作
9.4.1导出js文件
function show() {
console.log('show')
}
function sum() {
console.log('sum')
}
function People() {
}
People.prototype = {
showName: function (something) {
console.log(something)
}
}
let a = 1;
let b = 2;
export {
show,
sum,
a,
b
}
let mod = {
People
}
export default mod
9.4.2引入js文件
import mod, {
show, sum, a, b } from '../../model/index-1.js'//相对路径
new mod.People().showName('工作');//工作
show();//show
sum();//sum
console.log(a)//1
console.log(b)//2
10类(class)和继承
10.0注意点
10.0.1关于[里面放变量名称]
let aaa = 'xbc';
let bbb = 'wyt';
function func(a, b) {
return a + b;
}
let funcObj = {
[func(aaa, bbb)]: '你好!'
};
console.log(funcObj);//{xbcwyt:"你好!"}
let json = {
[aaa + bbb]: 'hello'
}
console.log(json);//{xbcwyt:"hello"}
10.0.2class没有预解析的功能
let p = new Person();//Uncaught ReferenceError: Cannot access 'Person' before initialization
class Person {
constructor() {
this.name = 996
}
}
10.0.3矫正this
- call(需要this指向的,参数一,参数二,参数三……)
- apply(需要this指向的,[‘参数一’,‘参数二’,‘参数三’]……)//这两个都会自调用
- bind(需要this指向的)//返回的是一个函数,需要手动调用
function func() {
console.log(this);
};
func.call({
})//{}
func.apply({
})//{}
func.bind({
})()//{}
class Person {
constructor() {
this.name = '李四'
console.log(this)
}
showName() {
return `名字${
this.name}`
}
}
let people = new Person();
let {
showName } = people;//解构赋值
console.log(showName.bind(people)())//将本来指向window的this指向people
10.1class里面的取值函数(getter),存值函数(setter) 用的比较少
class Person {
constructor() {
}
set name(value) {
console.log('设置name属性为' + value)//设置name属性为张三
}
get name() {
return `获取name的属性`;
}
}
let people = new Person();//是一个对象
people.name = '张三';//给对象设置一个私有属性 设置的时候就会自己调用set name方法了
console.log(people.name)//获取name的属性 取得时候就会调用get name 方法了
10.2静态方法
class Person {
constructor() {
}
showName() {
return `这是showName方法`
}
static aaa(){
//定义静态方法
return '静态方法'
}
}
let people = new Person();//是一个对象
console.log(people.showName())//这是showName方法
console.log(Person.aaa())//静态方法 //静态方法可以直接通过person调用,不用new
10.3使用函数模拟
10.3.1函数模拟类
function People(name = '张三', age = '18') {
this.name = name;
this.age = age
}
People.prototype = {
constructor: People,
skills: function (someThing = '技术支持') {
console.log(`你好,我叫${
this.name}今年${
this.age}我会${
someThing}`)
}
};
function animal(name = '狮子', subject = '猫科') {
this.name = name;
this.subject = subject
}
// animal.prototype = {
// life: function (where = '非洲大草原') {
// console.log(`这是${this.name}所属${this.subject}生活在${where}`)
// }
// }
Object.assign(animal.prototype, {
//本质上都是往prototype上添加类
life(where = '非洲大草原') {
console.log(`这是${
this.name}所属${
this.subject}生活在${
where}`)
}
})
let p = new People('李四', 12);
let a = new animal('老虎', '虎类');
p.skills('跳舞');//你好,我叫李四今年12我会跳舞
a.life('东北森林');//这是老虎所属虎类生活在东北森林
10.3.2函数模拟类继承
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
};
Person.prototype.showInfo = function () {
return `我叫${
this.name},性别${
this.sex},今年${
this.age}了`
};
function Child(name, age, sex, skill) {
Person.call(this, name, age, sex);
this.skill = skill;
};
Child.prototype = new Person();
Child.prototype.showSkill = function () {
console.log(this.showInfo());//我叫张三,性别男,今年12了
return `我叫${
this.name},性别${
this.sex},今年${
this.age}了,技能${
this.skill}`;
};
let c = new Child('张三', 12, '男', '前端开发');
console.log(c.showInfo());//我叫张三,性别男,今年12了
console.log(c.showSkill());//我叫张三,性别男,今年12了,技能前端开发
10.4使用类
class Person {
constructor(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
showInfo() {
return `我叫${
this.name},性别${
this.sex},今年${
this.age}了`
}
};
let p = new Person('张三', 16, '男');
console.log(p.showInfo());//我叫张三,性别男,今年16了
10.5类继承
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
information(where) {
console.log('父级的方法')
return `你好,我叫${
this.name}今年${
this.age}岁了,我在${
where}工作`
}
}
class Student extends Person {
//继承父类
constructor(name, age, sex, workType) {
super(name, age);//调用父类的属性
this.sex = sex;
this.workType = workType;
}
information1(where) {
//当子类的名称和父类一致时,子类会覆盖父类的方法名称如果不想覆盖需要在子类中调用 super.Information()//然后在处理子类的逻辑即可
return `你好,我叫${
this.name}性别${
this.sex}今年${
this.age}岁了,我在${
where}工作,工作岗位是${
this.workType}`
}
}
let student = new Student('张三', 26, '男', 'web开发工程师');
console.log(student.information('天津'))//你好,我叫张三今年26岁了,我在天津工作
console.log(student.information1('天津'))//你好,我叫张三性别男今年26岁了,我在天津工作,工作岗位是web开发工程师
10.6实例一:实现拖拽功能
class Drag {
constructor(id) {
this.id = document.querySelector(id);
this.divInsideMouseX = 0;
this.divInsideMouseY = 0;
this.init();//自调用一下,也可以称之为初始化
}
init() {
this.id.onmousedown = function (e) {
e.preventDefault();//取消选中文字
this.divInsideMouseX = e.clientX - this.id.offsetLeft;//获取鼠标在div内的位置
this.divInsideMouseY = e.clientY - this.id.offsetTop;
document.onmousemove = this.mouseMove.bind(this);
document.onmouseup = this.mouseUp.bind(this)
}.bind(this)//将this的指向由事件源指向Drag对象
}
mouseMove(e) {
this.id.style.left = e.clientX - this.divInsideMouseX + 'px';
this.id.style.top = e.clientY - this.divInsideMouseY + 'px';
}
mouseUp() {
//当鼠标抬起的时候取消绑定事件
document.onmousemove = null;
document.onmouseup = null;
}
}
new Drag('#div1');
class ChildrenDrag extends Drag {
//子类继承父类
//限制拖动的范围
mouseMove(e) {
//限制范围在move中就可以所以需要重写move
super.mouseMove(e);//重写之前要调用父级
if (this.id.offsetLeft < 0) {
this.id.style.left = 0;
}
if (this.id.offsetLeft > document.documentElement.clientWidth - this.id.offsetWidth) {
this.id.style.left = document.documentElement.clientWidth - this.id.offsetWidth + 'px';
}
if (this.id.offsetTop < 0) {
this.id.style.top = 0;
}
if (this.id.offsetTop > document.documentElement.clientHeight - this.id.offsetHeight) {
this.id.style.top = document.documentElement.clientHeight - this.id.offsetHeight + 'px';
}
}
}
new ChildrenDrag('#div2')
11.es6
新增的数据类型symbol
- 数据类型
数据类型={
number,
string,
boolean,
object,
underfind,
function,
symbol//es6新加的数据类型,基本类型
}
- 基本数据类型有这六种:undefined、null、string、number、boolean、symbol(es6)。
引用类型有这几种:Object、Array、RegExp、Date、Function、特殊的基本包装类型(String、Number、Boolean)以及单体内置对象(Global、Math)。
11.1Symbol前面不能加new,加new报错因为Symbol并不是一个构造函数
let syml = Symbol('bbb');
console.log(syml);//Symbol(bbb)
11.2Symbol()返回的都是唯一值 一般做一个key,定义一些唯一或者私有的东西
let symbol = Symbol('name');
let json = {
a: 'apple',
b: 'banana',
[symbol]: 'symbol'//可以作为一个唯一的key值
}
console.log(json.a)//apple
console.log(json['a'])//apple
console.log(json[symbol])//symbol
for (let [key, value] of Object.entries(json)) {
//注意点:如果用symbol作为key值,是不能用for in循环出来的
console.log(key, value)
//a apple
//index-1.js?0ad2:16 b banana
}
12.generator函数
12.1基本使用
function* gen() {
//在function和函数名之间加一个*就代表是generator函数
yield 'welcome';//yidle只能在这个函数内部使用
yield 'to';
return '牧马人!';
}
let genJson = gen()//返回的是一个generator对象
console.log(genJson.next())//{value: "welcome", done: false} done的意思就是完成没有,现在后面还有yield,所以是false
console.log(genJson.next())//{value: "to", done: false}
console.log(genJson.next())//{value: "牧马人!", done: true}
//上述调用,都是手动调用,十分麻烦 因为generator是一个迭代器,所以可以使用循环,但是只能使用for of循环
for (let value of genJson) {
console.log(value)//注意点,遍历出来的只能是yield的东西,return是不能被遍历的
}
12.2generator配合解构赋值
function* gen() {
yield 'welcome';
yield 'to';
return 'China';
};
let genJson = gen();
let [a, b, c] = genJson;//解构赋值,只能解构yield对应的值
console.log(a, b, c)//welcome to undefined
let [a, ...b] = genJson;//解构赋值,只能解构yield对应的值
console.log(a, b)//welcome ["to"]//这里面的a b 是随便定义的
console.log(...genJson)//welcome to
console.log(Array.from(gen()))//["welcome", "to"]
12.3应用实例
function* gen() {
let val = yield 'itstrive';
yield axios({
method: 'get',
url: 'https://api.github.com/users/' + val
})
}
let g1 = gen();
let userName = g1.next().value;
console.log(userName)//itstrive
console.log(g1.next(userName).value)//Promise 对象//所以能用then
g1.next(userName).value.then(res => {
//
console.log(res)//{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
});
13.同步异步
- 异步:不连续,上一个操作没有执行完毕,下一个操作照样可以开始
- 同步:连续执行,上一个操作没有执行完毕,下一个操作不能开始
- 关于异步,解决方案:
- 回调函数的方案
- 事件监听方式
- 发布/订阅
- Promise对象
13.1利用promise解决异步回调问题
const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
return new Promise((resolve, reject) => {
//新建一个promise对象并返回出去
fs.readFile(fileName, (err, data) => {
//接收文件名
if (err) reject(err);//如果报错
resolve(data);//成功
})
})
}
//promise
readFile('data/a.txt').then(res => {
//将文件路径传到函数中,并调用then
console.log(res.toString());//aaaaaaaaaaa
return readFile('data/b.txt');// 将文件路径传到函数中
}).then(res => {
console.log(res.toString());//bbbbbbbbbbbb
return readFile('data/c.txt') //将文件路径传到函数中
}).then(res => {
console.log(res.toString());//cccccccccccccccccc
})
13.2利用generator解决异步问题
const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
return new Promise((resolve, reject) => {
fs.readFile(fileName, (err, data) => {
if (err) reject(err);
resolve(data);
})
})
}
//generator
function* gen() {
//将所有的文件路径都放在gen中
yield readFile('data/a.txt');
yield readFile('data/b.txt');
yield readFile('data/c.txt');
}
let g1 = gen();
g1.next().value.then(res => {
console.log(res.toString())//aaaaaaaaaaa
return g1.next().value//返回promise对象
}).then(res => {
console.log(res.toString())//bbbbbbbbbbbb
return g1.next().value;
}).then(res => {
console.log(res.toString())//cccccccccccccccccc
})
13.3利用async处理异步函数
const fs = require('fs');
//简单封装 将fs封装成一个promise版本
const readFile = function (fileName) {
return new Promise((resolve, reject) => {
fs.readFile(fileName, (err, data) => {
if (err) reject(err);
resolve(data);
})
})
}
//asyns
async function fn() {
//asyns表明这是一个异步函数 await意思是,当程序执行到这里的时候需要等待,直到加载在往下走
let f1 = await readFile('data/a.txt')
console.log(f1.toString());//aaaaaaaaaaa //自动调用
let f2 = await readFile('data/b.txt')
console.log(f2.toString());//bbbbbbbbbbbb
let f3 = await readFile('data/c.txt')
console.log(f3.toString());//cccccccccccccccccc
}
fn();
13.4asyns特点
asyns function func(){
//表示异步,这个函数里面有异步的任务
let result=await xxx//表示结果需要等待
}
- await只能放到asyns中
- 语义化更强了
- await后面可以是promise对象,也可以是数字,字符串,布尔
- asyns函数返回的是一个promise对象
13.5async基本使用
async function func() {
return '你好'
};
console.log(func());//Promise {<fulfilled>: "你好"}
func().then(res => {
console.log(res);//你好
})
13.6await语句后面promise状态变成reject,那么整个async函数就会中断执行
async function func() {
let res1 = await Promise.reject('出bug了');
console.log(res1);//'出bug了'
let res2 = await Promise.resolve('success');
console.log(res2);//中断
let res3 = await Promise.resolve('success');
console.log(res3);//中断
};
func();
13.7不想当一个函数出现问题时,就中断整个请求,就需要用到try和catch
async function func() {
try {
let res1 = await Promise.reject('出bug了');
console.log(res1);//'出bug了'
} catch (e) {
}
try {
let res2 = await Promise.reject('出bug了');
console.log(res2);//success
} catch (e) {
}
try {
let res3 = await Promise.resolve('success');
console.log(res3);//success
} catch (e) {
}
};
func();
13.8利用promise本身的catch解决
async function func() {
let res1 = await Promise.reject('出bug了').catch(res => {
console.log(res);//'出bug了'
})
console.log(res1);//undefined
let res2 = await Promise.reject('出bug了').catch(res => {
console.log(res);//出bug了
})
console.log(res2);//undefined
let res3 = await Promise.resolve('success').catch(res => {
console.log(res);
})
console.log(res3);//success
};
func();
13.9任何有await地方都有需要catch掉
async function func() {
try {
let res = await axios({
method: 'get',
url: 'http://jsonplaceholder.typicode.com/posts'
})
let res1 = await axios({
method: 'get',
url: 'http://jsonplaceholder.typicode.com/posts/1'
})
console.log(res1);
console.log(res);
} catch (e) {
}
try {
} catch (e) {
}
};
func();