【前端】ECMAScript6从入门到进阶

【前端】ECMAScript6从入门到进阶

1.ES6简介及环境搭建

1.1.ECMAScript 6简介

在这里插入图片描述

(1)ECMAScript 6是什么

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

(2)ECMAScript 和 JavaScript 的关系

ECMAScript是JavaScript的标准,JavaScript是ECMAScript的实现。换句话说,如果说JavaScript是一门语言的话,那么ECMAScript就是这门语言遵循的语法书。

(3)ES6 与 ECMAScript 2015 的关系

2011年的时候,ECMAScript 5.1版本发布,ECMA组织就开始准备6.0版本了。但因为这个版本引入的语法功能太多了,所以不可能通过一个版本就将所有功能涵盖。所以,标准委员会决定,标准在每年的6月份正式发布一次,作为当年的正式版本。接下来的时间,就在这个版本的基础上做改动,直到下一年的6月份,草案就自然变成了新一年的版本。这样一来,就不需要以前的版本号了,只要用年份标记就可以了。

就这样ES6的第一个版本就在2015.6正式发布了,正式名称就是《ECMAScript 2015标准》(简称ES2015)。

1.2.babel工具搭建ES6环境

采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

  • 首先确保环境中有node
node安装:http://nodejs.cn/download/
  • 初始化工程项目
// 使用默认配置初始化项目
npm init -y
  • 安装对应的依赖包
// 本地安装babel-cli及对应的转化规则
npm install --save-dev babel-cli babel-preset-es2015// 阿里巴巴定制的镜像源
npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 创建项目目录

    • src目录用于存放编写的es6代码

    • dist目录用于存放由es6转化后的代码

  • 配置babel

新建.babelrc文件

// 配置用于转化当前代码的规则集
{"presets": ["es2015"]
}

babel的基本用法

// -o 参数指定输出文件
node_modules/.bin/babel src/index.js -o dist/index.js// -d 参数指定输出目录
node_modules/.bin/babel src -d dist

配置package.json文件实时编译

// 配置启动脚本的命令
"scripts": {// 监听index.js文件,一发生变化就执行babel转译的命令"dev": "babel src -w -d dist",
}

2.新的声明及数据赋值方式

2.1.变量声明let与const

作用域就是变量的有效范围,之前只有全局作用域和函数作用域,现在新增块级作用域。es6中新增let和const两种变量声明方式。

(1)let和const的相同点

  • 只在声明的代码块内有效
if (true) {var a = "a";
}
console.log(a);
// let声明变量,const同理
if (true) {let b = "b";
}
console.log(b);

在这里插入图片描述

  • 在同一作用域内不允许重复声明

在这里插入图片描述

  • 没有变量提升,在声明变量前,不能使用该变量
console.log(a);
var a = 'a';console.log(b);
let b = '1';

在这里插入图片描述

用var声明的变量会存在变量提升的问题,如果用let或者const就会消除变量提升问题,在遇到未定义的变量直接抛错。

(2)let和const的区别

  • const用来声明一个只读的变量
const x = 10;
x = 13;
console.log(x);

注意:const声明的变量同时必须立即赋值,如声明的是简单类型的数据,变量的值不可改变。

在这里插入图片描述

2.2.ES6新数据类型Symbol

在ES6之前JavaScript的原始数据类型有Number、String、Boolean、Null、Undefined。ES6中增加新的Symbol独一无二的类型。

对象的属性名容易产生命名冲突,为保证键名的唯一性,故es6引入Symbol这种新的原始类型数据,确保创建的每个变量都是独一无二的。

  • Symbol类型的数据是类似字符串的数据类型。
  • 由于Symbol函数返回的值是原始类型的数据,不是对象,故Symbol函数前不能使用new命令,否则会报错。
let s = Symbol();
console.log(typeof s);

在这里插入图片描述

let s1 = Symbol();
let s2 = Symbol();
console.log(s1===s2);let l1 = Symbol('lixiang');
let l2 = Symbol('lixiang');
console.log(l1===l2);

在这里插入图片描述

定义对象的唯一属性名

// 在对象里用Symbol作为属性名的三种写法
let s = Symbol();// 第一种方式: 借助数组读取s变量,此时不能用点运算符,点运算符默认后面的参数是字符串
let a = {};
a[s] = 'lixiang'// 第二种方式: 构造时声明
let a = {[s]: 'lixiang'
}// 第三种 Object.defineProperty
let a = {};
Object.defineProperty(a, s, { value: 'lixiang' });

在这里插入图片描述

定义常量

const s = Symbol("李祥");

在这里插入图片描述

2.3.解构赋值详解

(1)什么是解构赋值

解构赋值可以理解为赋值操作的语法糖,它是针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。代码书写上言简意赅,语义明确,也方便了对象数组的读取操作。

ES6中只要某种数据可以循环迭代,都可以进行解构赋值。

(2)数组解构

// 变量多时,对应不上的变成undefined
let [a, b, c] = [1, 2];
console.log(a, b, c);

在这里插入图片描述

// 变量默认值,声明变量时将c默认成6
let [a, b, c = 6] = [1, 2];
console.log(a, b, c);

在这里插入图片描述

// 分割数组,将1赋值给a,2,3成一个新数组
let [a, ...other] = [1, 2, 3];
console.log(a, other);

在这里插入图片描述

// 空内容,将a赋值为1,b赋值为3
let [a,,b] = [1, 2, 3];
console.log(a, b);

在这里插入图片描述

(3)对象解构

//1赋值为a,2赋值为b
let { a, b } = { a: 1, b: 2 };
console.log(a, b);

在这里插入图片描述

//重命名
let { a: aa, b: bb } = { a: 1, b: 2 };
console.log(aa, bb);

在这里插入图片描述

(4)读取接口返回的数据

function fun() {return {name: "张三",hobby: [{title: "篮球",},{title: "唱",},{title: "RAP",},{title: "跳",},],};
}
let {name,hobby: [{ title }],
} = fun();
console.log(name, title);

3.ES6新增的数据操作方法

3.1.ES6提供的新的字符串方法

(1)新增的API

方法描述
includes(string, index)判断字符串中是否包含指定字符串,返回值是布尔值
startsWith(string, index)判断字符串的开头是否包含指定字符串,返回值是布尔值
endsWith(string, index)判断字符串的尾部是否包含指定字符串,返回值是布尔值
repeat(n)repeat() 方法返回一个新字符串,表示将原字符串重复n 次。
padStart(length, str)字符串补齐,用于头部补全
padEnd(length, str)字符串补齐,用于尾部补全
//判断str是否包含an
let str = 'lixiang';
console.log(str.includes('an'));
//从下标为5的字符开始判断是否含an
console.log(str.includes('an',5));

在这里插入图片描述

//判断str是否以l开头
let str = 'lixiang';
console.log(str.startsWith('l'));
//从下标为3的字符开始判断是否以l开头
console.log(str.startsWith('l',3));

在这里插入图片描述

//判断str是否以g结尾
let str = 'lixiang';
console.log(str.endsWith('g'));
//从下标为3的字符开始判断是否以g结尾
console.log(str.startsWith('g',3));

在这里插入图片描述

//入参数字为2,重复两次
let str = 'lixiang';
console.log(str.repeat(2));

在这里插入图片描述

//在lixiang前面补a,补够10位
let str = 'lixiang';
console.log(str.padStart(10, 'a'));

在这里插入图片描述

//在lixiang后面补a,补够10位
let str = 'lixiang';
console.log(str.padEnd(10, 'a'));

在这里插入图片描述

(2)模板字符串

在ES5的时候拼接字符串我们往往这样写。

const name = '李祥';
const age = 18;
const hobbies = '写代码';
const str = '我叫'+name+',今年'+age+'岁,'+'喜欢'+hobbies+'。'

在ES6中新引入的模版字符串,写法如下。

const str = `我叫${name},今年${age}岁,喜欢${hobbies}`
console.log(str);

在这里插入图片描述

(3)使用模板字符串的注意事项

  • 使用模板字符串表示多行字符串时,所有的空格和缩进都会被保留在输出之中。
  • 模板字符串中引入变量,要用 ${变量名} 这样的形式引入才可以。
  • 模板字符串中的${…} 大括号内部可以放入任意的 JavaScript 表达式,可以进行运算、可以引用对象属性、可以调用函数、可以甚至还能嵌套,甚至还能调用自己本身。
3.2.ES6扩展运算符的使用

(1)深拷贝一维数组

const list = [1, 2, 3, 4, 5];
const listCopy = [...list];
console.log(listCopy);

在这里插入图片描述

(2)分割数组

const list = [1, 2, 3, 4, 5];
const [, ...list1] = list;
console.log(list1);

在这里插入图片描述

(3)将数组转化成参数传递给函数

const list = [1, 2];
function fun(a, b) {console.log(a + b);
}
fun(...list);

在这里插入图片描述

3.3.ES6数组的扩展方法

(1)fill:替换数组中的元素,会改变原数组。想要不改变原数组的值,可以采用深拷贝。

const list = [1, 2, 3, 4, 5];
//全部替换成6
const list1 = [...list].fill(6);
//下标从1开始到下表为4之间左闭右开,全部替换成6
const list2 = [...list].fill(6, 1, 4);
console.log(list);
console.log(list1);
console.log(list2);

在这里插入图片描述

(2)find:查询数组中符合条件的元素。

const list = [{ name: "李祥", age: 15 },{ name: "张三", age: 10 },{ name: "李四", age: 19 },{ name: "王武", age: 20 },
];
const result = list.find(function (item) {return item.name === "李祥";
});
console.log(result);

在这里插入图片描述

(3)findIndex:查询数组中符合条件的元素的索引。

const result = list.findIndex(function (item) {return item.name === "李祥";
});
console.log(result);

在这里插入图片描述

(4)flat:用于合并数组。

const list = [1, 2, 3, [4, 5, 6, [ 7, 8]]];
const list2 = list.flat(2);
console.log(list2);

在这里插入图片描述

(5)filter:过滤出符合条件的元素,与find不同的是filter返回一个数组。

const result = list.filter(function (item) {return item.name === "李祥";
});
console.log(result);

在这里插入图片描述

3.4.ES6数组中map方法

map用于将一个类型的数字转换成另外一个类型。

const list = [{ name: "李祥", age: 15 },{ name: "张三", age: 10 },{ name: "李四", age: 19 },{ name: "王武", age: 20 },
];
//遍历集合中每一项,创建obj对象,将原对象属性复制到新的obj中
//然后给obj增加一个属性state
const mapList = list.map(function (i) {let obj = {};//对象拷贝Object.assign(obj, i);obj.sex = 0;return obj;
});
console.log(mapList);

在这里插入图片描述

3.5.ES6对象的新特性

创建对象

const a = {name: 'lixiang',age: 21,address: {city: 'BeiJing',town: 'ChangYang'},
};

(1)深拷贝简单对象

const b = { ...a };
console.log(b);

在这里插入图片描述

(2)给对象设置默认值

const b = { ...a, name: 'zhangsan' };
console.log(b);

在这里插入图片描述

(3)合并对象

const b = { sex:'0' };
const c = {...a,...b}
console.log(c);

在这里插入图片描述

(4)属性初始化、方法的简写

在这里插入图片描述

(5)Object新增的方法

  • Object.is:判断两个对象是否相等
let res = Object.is({name:'lx'}, {name:'lx'});
console.log(res);
let res1 = Object.is(NaN, NaN);
console.log(res1);

在这里插入图片描述

  • Object.assign:对象复制
let a = { name: 'lx', age: 24 };
let b = {};
let c = Object.assign(b, a);
console.log(c);

在这里插入图片描述

  • Object.keys:获取对象所有的key
let a = { name: 'lx', age: 24 };
const arr = Object.keys(a);
console.log(arr);

在这里插入图片描述

  • Object.values:获取对象所有的value
let a = { name: 'lx', age: 24 };
const arr = Object.values(a);
console.log(arr);

在这里插入图片描述

  • Object.entries:获取key和value
let a = { name: 'lx', age: 24 };
const arr = Object.entries(a);
console.log(arr);

在这里插入图片描述

3.6.ES6新增Map与WeakMap

JavaScript中的对象,实质就是键值对的集合,但是在对象里却只能用字符串作为键名。在一些特殊的场景里就满足不了我们的需求了,正因为此,Map这一数据提出了,它是JavaScript中的一种更完善Hash结构。

Map对象:用于保存键值对,任何值(对象或者原始值)都可以作为一个键名或一个值。

  • 属性及方法
属性/方法作用例子
size返回键值对的数量m.size
clear()清除所有键值对m.clear()
has(key)判断键值对中是否有指定的键名,返回值是布尔值m.has(key)
get(key)获取指定键名的键值,如不存在则返回undefinedm.get(key)
set(key, value)添加键值对,如键名已存在,则更新键值对m.set(key, value)
delete(key)删除指定键名的键值对m.delete(key)

(1)创建一个Map

//创建一个空map
let map = new Map();
//创建一个带有默认值的map
let mapDef = new Map([['name','lx'],['age',12]
]);
console.log(map);
console.log(mapDef);

在这里插入图片描述

(2)API演示

//创建一个空map
let map = new Map();
//map中增加一个元素
map.set('name','lx');
map.set('age',20);
console.log(map);
//map中修改一个元素
//map中set方法如果有key则覆盖,没有则新增
map.set('name','zs');
console.log(map);
//返回键值对的数量
console.log(map.size);
//判断是否有某个key
console.log(map.has('name'));
//获取某个key的value
console.log(map.get('name'));
//删除某个key
map.delete('name');
console.log(map);
//清空
map.clear();
console.log(map);

在这里插入图片描述

(3)遍历器生成函数

const keys = map.keys();
const values = map.values();
const entries = map.entries();
console.log(Array.from(keys));
console.log(Array.from(values));
console.log(Array.from(entries));

在这里插入图片描述

WeakMap:只接受对象作为键名,而且无法遍历

const weakMap = new WeakMap([[{ name: 'lx' ,age: 21},{id:1,hobby:'唱、跳、rap、篮球'}]]);
console.log(weakMap);

在这里插入图片描述

在这里插入图片描述

3.7.ES6新增Set与WeakSet

Set是ES6给开发者提供的一种类似数组的数据结构,可以理解为值的集合。它和数组的最大的区别就在于: 它的值不会有重复项。

Set保证成员值唯一,用于集合去重。

  • 属性及方法
属性/方法作用例子
add新增元素s.add(key)
size返回成员个数s.size
clear()清除所有成员s.clear()
has(value)判断键值对中是否有指定的值,返回值是布尔值s.has(key)
delete(value)删除指定值s.delete(key)

(1)创建一个Set

const a = { name: 'lx' };
const set = new Set([a]);
console.log(set);const list = new Set([1, 2, 3, 4]);
console.log(list);

在这里插入图片描述

(2)API演示

const set = new Set([1, 2, 3, 4]);
console.log(set);
//获取set长度
console.log(set.size);
//判断是否存在2元素
console.log(set.has(2));
//删除2元素
set.delete(2);
console.log(set.has(2));

在这里插入图片描述

WeakSet:数组成员必须是对象

  • WeakSet结构也提供了add( ) 方法,delete( ) 方法,has( )方法给开发者使用,作用与用法跟Set结构完全一致。
  • WeakSet 结构不可遍历。因为它的成员都是对象的弱引用,随时被回收机制回收,成员消失。所以WeakSet 结构不会有keys( ),values( ),entries( ),forEach( )等方法和size属性。
3.8.Array与Set的转换
// 数组转set
const list = [1, 2, 3];
const set = new Set(list);
console.log(set);// set转数组
const arr = Array.from(set);
console.log(arr);
3.9.Object与Map的转换
// 对象转map
const obj = { nane: 'lx', age:24 };
const map = new Map(Object.entries(obj));
console.log(map);// map转对象
const obj1 = Object.fromEntries(map);
console.log(obj1);

4.ES6新增高阶知识点

4.1.ES6中新增代理Proxy

(1)Proxy简介

正如Proxy的英译"代理"所示,Proxy是ES6为了操作对象引入的API。它不直接作用在对象上,而是作为一种媒介,如果需要操作对象的话,需要经过这个媒介的同意。

(2)使用方式

/* @params
** target: 用Proxy包装的目标对象
** handler: 一个对象,对代理对象进行拦截操作的函数,如set、get
*/
let p = new Proxy(target, handler)

(3)案例实战

const house = {name: '三室一厅-次卧',price: 1000,phone: '18823139921',id: '20230131',state: '**',
};const handle = {get: function (obj, key) {switch (key) {case 'price':return obj[key] + 500;case 'phone':return obj[key].substring(0, 3) + '****' + obj[key].substring(7);default:return obj[key];}},set: function (obj, key, value) {if (key === 'state') {obj[key] = value;}},
};const houseproxy = new Proxy(house, handle);
console.log(houseproxy.id);
console.log(houseproxy.phone);
console.log(houseproxy.price);
houseproxy.state='****';
console.log(houseproxy.state);

在这里插入图片描述

4.2.ES6中新增反射Refect

(1)Reflect简介

与Proxy相同,ES6引入Reflect也是用来操作对象的,它将对象里一些明显属于语言内部的方法移植到Reflect对象上,它对某些方法的返回结果进行了修改,使其更合理,更具语义化,并且使用函数的方式实现了Object的命令式操作。

  • 属性及方法
属性/方法作用
Reflect.apply(target, thisArg, args)对一个函数进行调用操作,同时可以传入一个数组作为调用参数。
Reflect.construct(target, args)对构造函数进行 new 操作,相当于执行 new target(…args)。
Reflect.get(target,name, receiver)获取对象身上某个属性的值,类似于 target[name]。如果没有该属性,则返回undefined。
Reflect.set(target, name,value, receiver)Reflect.defineProperty方法基本等同于Object.defineProperty,直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,不同的是,Object.defineProperty返回此对象。而Reflect.defineProperty会返回布尔值
Reflect.has(target,name)判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
Reflect.ownKeys(target)返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable影响, Object.keys返回所有可枚举属性的字符串数组).
Reflect.isExtensible(target)判断一个对象是否是可扩展的(是否可以在它上面添加新的属性),类似于 Object.isExtensible()。返回表示给定对象是否可扩展的一个Boolean 。(Object.seal 或 Object.freeze 方法都可以标记一个对象为不可扩展。)
Reflect.preventExtensions(target)让一个对象变的不可扩展,也就是永远不能再添加新的属性。
4.3.Proxy实现数据双向绑定

(1)需求

实现一个双向的数据绑定。

在这里插入图片描述

(2)实现

  • 编写html代码
<body>请输入内容:<input type="text" id = "input"/><br/>实时内容展示:<span id = "span"></span><script src="./js/index.js"></script>
</body>
  • 编写js代码
// 获取dom节点
const input = document.getElementById("input");
const span = document.getElementById("span");
//定义双向绑定的对象
let obj = {};//定义代理对象的handle方法
const handle = {get: function (target, key) {return target[key];},set: function (target, key, value) {if (key === "text" && value) {span.innerHTML = value;return (target[key] = value);}},
};//创建代理对象
const proxy = new Proxy(obj, handle);//创建键盘的监听事件
input.addEventListener("keyup", function (e) {proxy.text = e.target.value;console.log(proxy.text);
});

5.函数的扩展、类及模块化

5.1.函数参数的扩展

(1)函数参数可设置默认值

//求和方法,当a和b都不传值时,默认都为1
function sum(a = 1, b = 1) {return a + b;
}
console.log(sum());
console.log(sum(3));
console.log(sum(3,5));

在这里插入图片描述

(2)rest参数,可变参数

//求和方法,可变参数
function sum(...rest) {let num = 0;rest.forEach((e)=>{num+=e;})return num;
}
console.log(sum(...[1,2]));
console.log(sum(...[1,2,4]));

在这里插入图片描述

5.2.ES6新增箭头函数

(1)箭头函数简介

ES6中允许使用=>来定义函数。箭头函数相当于[匿名函数,并简化了函数定义。

箭头函数在语法上比普通函数简洁多。箭头函数就是采用箭头=>来定义函数,省去关键字function。

无参:()=>{},等同于:function (){}
有参:(a,b)=>{},等同于:function (a,b){}

(2)箭头函数不绑定this

//箭头函数this指当前块级作用域
const obj = {num: 10,sum() {setTimeout(() => {console.log(this.num);}, 1000);},
};
obj.sum();

在这里插入图片描述

如果不是箭头函数,setTimeout()函数调用指的是当前window。

const obj = {num: 10,sum() {setTimeout(function (){console.log(this);}, 1000);},
};
obj.sum();

在这里插入图片描述

(3)什么情况下不能箭头函数

  • 定义对象的方法
const obj = {num: 10,sum:() => {setTimeout(() => {console.log(this.num);}, 1000);},
};
obj.sum();

在这里插入图片描述

  • 箭头函数没有arguments
const fun = () => {console.log(arguments);
};
fun();

在这里插入图片描述

  • 定义构造函数
const Car = () => {console.log(this);
};
let car = new Car();

在这里插入图片描述

  • 定义DOM事件的回调函数
const span = document.getElementById("span");
span.addEventListener("click", () => {console.log(this);this.innerHTML = "触发事件";
});

在这里插入图片描述

在这里插入图片描述

const span = document.getElementById("span");
span.addEventListener("click", function () {console.log(this);this.innerHTML = "触发事件";
});

在这里插入图片描述

5.3.ES6中新引入类的概念

ES6之前javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。

(1)定义类

class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`我是${this.name},今年${this.age}`);}
}
const person = new Person("张三", 18);
person.sayHello();
console.log(person);

在这里插入图片描述

(2)类的继承,重写父类的方法

class Person {constructor(name, age) {this.name = name;this.age = age;}hello() {console.log(`我是${this.name},今年${this.age}`);}
}class Student extends Person {//子类重写父类属性constructor(name, age, sex) {super(name, age);this.sex = sex;}hello() {console.log(`我是${this.name},今年${this.age}岁,性别:${this.sex === '1'?'男':'女'}`);}
}const person = new Student('张三', 18,'1');
person.hello();
console.log(person);

在这里插入图片描述

(3)静态方法和静态属性

//静态方法和静态属性只能由类名进行调用
class Person {static eyes = '眼睛';static hello(){console.log(`我是${this.name}`);}
}console.log(Person.eyes);
Person.hello();

在这里插入图片描述

5.4.ES6新增模块化开发

ES6之前是没有类的概念的,也就没有模块这一说法。理想情况下,开发者应该只注重核心业务的开发,对于其他有一定通用性的业务可以直接引入,也就是模块。多人开发,本应如此。

  • CommonJS:Commonjs是作为Node中模块化规范以及原生模块面世的。
  • AMD和RequireJs:AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到所有依赖加载完成之后(前置依赖),这个回调函数才会运行。

Import 和 export案例

  • export.js
const name = '李祥';function hello(){console.log('hello word');
}class Car{constructor(name){this.name=name;}run(){console.log(this.name+'跑起来了');}
}export default{name,hello,Car,
}
  • Import.js
import test from './export.js';
console.log(test.name);
test.hello();
  • html中js引入要改成module类型
<script src="./js/import.js" type="module"></script>

在这里插入图片描述

6.ES6改进异步编程

6.1.Promise简介及案例

(1)什么是回调地狱

当异步操作想要有顺序时,只能在一个异步成功以后的回调函数里面嵌套另一个异步的操作,如果嵌套的层数过多就形成了回调地狱。

回调地狱的弊端:后期代码维护比较困难。

promise就是用来解决回调地狱。

promise封装了异步操作。创建一个promise对象,写一个函数作为参数,这个函数参数有两个参数,分别是resolve和reject。函数内部写异步操作,成功调resolve,失败调reject。这时promise对象就可以知道异步操作的状态。p.then(成功执行)p.catch(失败执行)。

promise本质就是一个状态机,记录异步内部操作的状态。

在es6之前写法代码耦合,出错时,无法排除。

function request() {axios.get("a.json").then((res) => {if (res && res.data.code === 0) {console.log(res.data.data.data);axios.get("b.json").then((res) => {if (res && res.data.code === 0) {console.log(res.data.data.data);axios.get("c.json").then((res) => {console.log(res.data.data.data);});}});}});
}request();
  • 简单说Promise就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
  • 从语法上说,Promise 是一个对象,从它可以获取异步操作的的最终状态(成功或失败)。
  • Promise 是一个构造函数,提供统一的 API,Promise里不仅可以存放着异步的代码,也可以放同步的代码。
// 准备阶段
new Promise((resolve, reject) => {})// 成功状态
new Promise((resolve, reject) => {resolve('成功'); // 同步代码
}).then((res) => {console.log(res);
});// 失败状态
new Promise((resolve, reject) => {reject('失败');
}).catch((err) => {console.log(err);
});

在这里插入图片描述

  • Promise对象的状态不受外界影响

    • pending 初始状态

    • resolve 成功状态

    • rejected 失败状态

      Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态

  • Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成resolve或者由pending变成rejected

(2)Promise解决回调地狱案例

//先定义三个函数
function requestA() {return new Promise((resolve, reject) => {axios.get("a.json").then((res) => {resolve(res);});});
}function requestB() {return new Promise((resolve, reject) => {axios.get("b.json").then((res) => {resolve(res);});});
}function requestC() {return new Promise((resolve, reject) => {axios.get("c.json").then((res) => {resolve(res);});});
}
function request() {requestA().then((res) => {console.log(res);return requestB();}).then((res) => {console.log(res);return requestC();}).then((res) => {console.log(res);});
}
request();

(3)Promise.all方法

  • Promise.all 实际上是一个函数,它接受一个 promise 数组并返回一个 promise。然后当所有的 promise 都完成时会得到结果数组或者当其中一个被拒绝时会抛出错误。
  • 返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
function requestAll() {Promise.all([requestA(), requestB(), requestC()]).then((res) => {console.log(res);}).catch((err) => {console.log(err);});
}
requestAll();

(4)Promise.race方法

Promse.race就是赛跑的意思,传入的promise 数组里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

function requestRace() {Promise.race([requestA(), requestB(), requestC()]).then((res) => {console.log(res);}).catch((err) => {console.log(err);});
}
requestRace();
6.2.优雅的异步编程async

(1)什么是async

async是异步的简写,Generator(生成器)的语法糖,用于声明一个函数是异步函数。

async function sum(a,b) {await console.log(a+b);
}
sum(1,2);

async 写在函数前,返回一个Promise对象。

async await改造promise.then异步调用。

async function request() {try {const a = await requestA();const b = await requestB();const c = await requestC();console.log(a, b, c);} catch (err) {console.log(err);}
}
request();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/144424.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于微信小程序的刷题考试系统设计与实现(适用于各类考试类、答题类程序)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

【IDEA】使用idea调试时查看对象集合的值

1、在实体类上添加toString方法 2、在要查看集合的地方右键View as→toString 3、View Text复制对象集合的值 4、复制map集合的值同理

[杂谈]-ESP32中的无线通信协议

ESP32中的无线通信协议 文章目录 ESP32中的无线通信协议1、ESP32 无线通信协议简介2、Bluetooth Low Energy (BLE)3、**Bluetooth Classic**4、**ESP-NOW**5、Wi-Fi&#xff08;客户端-服务器通信协议&#xff09;6、MQTT7、**LoRa**8、**GSM/GPRS/LTE**9、总结 ESP32是一个基于…

如何使用ArcGIS Pro直接获取道路中心线

以前使用ArcGIS获取道路中心线&#xff0c;需要先将面要素转换为栅格再获取中心线&#xff0c;现在我们可以通过ArcGIS Pro直接获取道路中心线&#xff0c;这里为大家介绍一下获取方法&#xff0c;希望能对你有所帮助。 新建地理数据库 在存储数据的文件夹上点击右键&#xff…

专栏更新情况:华为流程、产品经理、战略管理、IPD

目录 前言 01 华为流程体系入门课 CSDN学院 02 产品经理进阶课 CSDN学院 03 BLM 战略方法论进阶课 04 IPD 进阶 100 例专栏 作者简介 前言 已上线四大课程专栏更新情况&#xff1a; 01 华为流程体系入门课&#xff08;视频图文&#xff09;&#xff1b; 02 硬件产品经…

Linux文件查找,别名,用户组综合练习

1.文件查看: 查看/etc/passwd文件的第5行 [rootserver ~]# head -5 /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologi…

使用YOLOv5的backbone网络识别图像天气 - P9

目录 环境步骤环境设置包引用声明一个全局的设备 数据准备收集数据集信息构建数据集在数据集中读取分类名称划分训练、测试数据集数据集划分批次 模型设计编写维持卷积前后图像大小不变的padding计算函数编写YOLOv5中使用的卷积模块编写YOLOv5中使用的Bottleneck模块编写YOLOv5…

信息安全:网络物理隔离技术原理与应用.

信息安全&#xff1a;网络物理隔离技术原理与应用. 随着网络攻击技术不断增强&#xff0c;恶意入侵内部网络的风险性也相应急剧提高。满足内外网信息及数据交换需求&#xff0c;又能防止网络安全事件出现的安全技术就应运而生了&#xff0c;这种技术称为“物理隔离技术” 基本原…

企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…

照片后期处理软件DxO FilmPack 6 mac中文说明

DxO FilmPack 6 for Mac是一款照片后期处理软件。它可以模拟超过60种著名胶片品牌和类型的色彩和颗粒感&#xff0c;使照片具有复古、艺术和时尚风格。 ​DxO FilmPack 6 mac支持RAW和JPG格式的照片&#xff0c;并提供丰富的调整选项&#xff0c;如亮度、对比度、曝光、阴影和高…

web:[极客大挑战 2019]Upload

题目 页面显示为一个上传&#xff0c;猜测上传一句话木马文件 先查看源代码看一下有没有有用的信息&#xff0c;说明要先上传图片&#xff0c;先尝试上传含有一句话木马的图片 构造payload <?php eval($_POST[123]);?> 上传后页面显示为&#xff0c;不能包含<&…

MySQL 索引介绍和最佳实践

目录 一、前言二、索引类型1.1 主键索引&#xff08;PRIMARY KEY&#xff09;1.2 唯一索引&#xff08;UNIQUE&#xff09;1.3 普通索引&#xff08;NORMAL&#xff09;1.3.1 单列普通索引1.3.2 单列前缀普通索引1.3.3 多列普通索引1.3.4 多列前缀普通索引 1.4 空间索引&#x…

微信小程序开发基础(一)认识小程序

微信小程序&#xff0c;小程序的一种&#xff0c;英文名Wechat Mini Program&#xff0c;是一种不需要下载安装即可使用的应用&#xff0c;它实现了应用“触手可及”的梦想&#xff0c;用户扫一扫或搜一下即可打开应用。微信小程序是一种不用下载就能使用的应用&#xff0c;也是…

React(react18)中组件通信06——redux-toolkit + react-redux

React&#xff08;react18&#xff09;中组件通信06——redux-toolkit react-redux 1 前言1.1 redux 和 react-redux1.2 关于redux-toolkit1.2.1 官网1.2.2 为什么要用Redux Toolkit&#xff1f; 1.3 安装 Redux Toolkit1.4 Redux Toolkit相关API 2. 开始例子——官网例子2.1 …

更直观地学习 Git 命令

theme: condensed-night-purple 前言 本文参考于 Learn Git Branching 这个有趣的 Git 学习网站。 在该网站&#xff0c;可以使用 show command 命令展示所有可用命令。 你也可以直接访问网站的sandbox&#xff0c;自由发挥。 本地篇 基础篇 git commit git commit将暂…

文件I/O与标准I/O

如果不知道inode&#xff0c;请看这篇文章inode 我们知道当打开一个文件时&#xff0c;OS会先使用inode编号在磁盘文件系统里面去寻找这个文件&#xff0c;找到以后根据文件的属性为其创建一个内核层面的结构体来描述这个文件&#xff0c;该结构体里面含有文件的属性信息&#…

蓝桥杯 题库 简单 每日十题 day11

01 质数 质数 题目描述 给定一个正整数N&#xff0c;请你输出N以内&#xff08;不包含N&#xff09;的质数以及质数的个数。 输入描述 输入一行&#xff0c;包含一个正整数N。1≤N≤10^3 输出描述 共两行。 第1行包含若干个素数&#xff0c;每两个素数之间用一个空格隔开&…

SpringMVC+统一表现层返回值+异常处理器

一、统一表现层返回值 根据我们不同的处理方法&#xff0c;返回的数据格式都会不同&#xff0c;例如添加只返回true|false&#xff0c;删除同理&#xff0c;而查询却返回数据。 Result类 为此我们封装一个result类来用于表现层的返回。 public class Result {//描述统一格式…

测试OpenCvSharp库的模板匹配功能

微信公众号“Dotnet讲堂”的文章《c#实现模板匹配&#xff0c;并输出匹配坐标》&#xff08;参考文献1&#xff09;中介绍了采用OpenCVSharp库实现模板匹配功能&#xff0c;也即在目标图片中定位指定图片内容的示例&#xff0c;本文参照参考文献1-4&#xff0c;学习并测试OpenC…

基于SpringBoot的飘香水果购物网站

目录 前言 一、技术栈 二、系统功能介绍 水果信息管理 减积分管理 会员购买订单管理 首页 水果 购买水果订单管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网购物的飞速发展&#xff0c;一般企业都去创建属于自己的电商平台以及购物…