一、ES介绍

1.1 什么是ECAMScript

ES全称ECMAScript,是脚本语言的规范,而平时经常编写的JavaScript,是EcmaScript的一种实现,所以ES新特性其实指的就是JavaScript的新特性。

ECMAScript是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。

1.2 什么是ECMA-262

Ecma国际制定了许多标准,而ECMA-262只是其中的一个,所有的标准列表查看

http://www.ecma-international.org/publications/standards/Standard.htm

1.3 ECMA-262历史

http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

注:从ES6开始,每年发布一个版本,版本号比年份最后一位大1

1.4 谁在维护ECMA-262

TC39(Technical Committee 39)是推进ECMAScript发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果,谷歌,微软,因特尔等)。TC39定期召开会议,会议由会员公司的代表与特邀专家出席。

1.5 为什么要学习ES6

  • ES6的版本变动内容最多。具有里程碑意义
  • ES6加入许多新的语法特性,编程实现更简单、高效
  • ES6是前端发展趋势

1.6 ES6兼容性

http://kangax.github.io/compat-table/es6/ 可查看兼容性

二、ES6-let变量声明

1、let变量声明的格式

与 var 声明变量格式一样

2、let声明变量的特性

(1)变量不能重复声明

let star = '罗志祥';
let star = '小猪';

(2)块级作用域,代码只在代码块内有效

{let girl = '周扬青';
}console.log(girl);    //控制台显示  girl is not defined

(3)不存在变量提升(变量在声明之前,不能使用该变量)

console.log(song);
let song = '稻香';    //控制台显示 Cannot access 'song' before initialization

(4)不影响作用域链

        {let school = '清华大学';function fn() {console.log(school);}fn();}

3、let件经典案例

let item = document.querySelectorAll('.item');
//1、常规var用法
for (var i = 0; i < item.length; i++) {item[i].addEventListener('click', function() {this.style.background = 'pink';})}//2、使用let变量声明用法
for (let i = 0; i < item.length; i++) {item[i].addEventListener('click', function() {item[i].style.background = 'pink';})}

三、ES6-conset声明常量

1、conset声明常量格式

常量:值不能修改的量

与var let 一样

2、注意事项

(1)一定要赋初始值

const A;   //报错

(2)一般常量使用大写(潜规则)

const a = 1000;

(3)常量的值不能修改

const SCHOOL = '清华大学';
SCHOOL = 'ATM';

(4)块级作用域

{const PLAYER = 'UZI';
}console.log(PLAYER);     //PLAYER is not defined

(5)对于数组和对象的元素修改,不算做对常量的修改,不会报错

const TEAM = ['UZI', 'MXLG', 'Ming', 'Letme'];
TEAM.push('Meiko');

四、ES6变量的解构赋值

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

1、数组的解构

const F4 = ['貂蝉', '蔡文姬', '虞姬', '甄姬'];
let [diao, cai, yu, zhen] = F4;
console.log(diao);    //貂蝉
console.log(cai);     //蔡文姬
console.log(yu);      //虞姬
console.log(zhen);    //甄姬

2、对象的解构

 const diao = {name: '貂蝉',age: '不详',zhandou: function() {console.log('我可以五连绝世');}};let {zhandou} = diao;
zhandou();   //我可以五连绝世

五、ES6模板字符串

ES6引入新的声明字符串的方式 :[``] 、  ' ' 、 " "。

1、声明

let str = `我也是一个字符串哦`;
console.log(str, typeof str);

2、特性

① 内容中可以直接出现换行符

let str = `<ul><li>王者荣耀</li><li>金铲铲之站</li><li>原神</li></ul>`;

② 可以直接进行变量拼装

let lovest = '林宥嘉';
let out = `${lovest}是我心目中最棒的歌手`;
console.log(out);   //林宥嘉是我心目中最棒的歌手

六、对象的简化写法

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法

这样的书写更加简洁

let name = '甄姬';let change = function() {console.log('阿宓会带来不幸');}const school = {name,change,improve() {console.log("我们可以提高你的技能");}}console.log(school);

七、箭头函数以及声明特点

ES6允许使用箭头(=>)定义函数

1、箭头函数语法结构

//1、常规写法
let fn = function() {}//2、使用箭头函数
let fn = () => {}//实例
let fn = (a, b) => {return a + b;}
let result = fn(1, 2);
console.log(result);         //3

2、特点

2.1  this是静态的,this始终指向函数声明时所在的作用域下的this的值

function getName () {console.log(this.name);}let getName2 = () >= {console.log(this.name);}//设置window对象的name属性
window.name = '吃什么';
const food = {name: "西瓜",}

2.2 箭头函数不能作为构造函数去实例化对象

let Person = (name, age) => {this.name = name;this, age = age;}let me = new Person('xiao', 30);console.log(me); //   Person is not a constructor

2.3 箭头函数不能使用arguments变量

let fn = () => {console.log(arguments);}
fn(1, 2, 3); //arguments is not defined

3、箭头函数的简写

3.1 当形参有且只有一个的时候,可省略小括号

//1、原始写法
let add = (n) => {return  n+n;}
console.log (add(9));//2、简写
let add = n => {return  n+n;}
console.log (add(9));    //18

3.2  当代码体只有一条语句的时候,此时return必须省略,语句的执行结果就是函数的返回值,此时省略花括号

//1、原始写法
let pow = (n) => {return n*n;}
console.log(pow(5));//2、简写
let pow = n => n*n;
console.log(pow(5));   //25

4、实践与应用

4.1  点击div 2s 后颜色变为天蓝色

<div class=“ad”></div>//1、原始写法
let ad = document.querySelectior('.ad');
ad.addEventListener('click',function(){// 保存this的值   因为此时定时器的初始写法为window.setTimeout(),需要特殊声明let _this = this;//定时器setTimeout(function(){_this.style.background = 'skyblue';}.2000);
});//2、简写
let ad = document.querySelectior('.ad');
ad.addEventListener('click',function(){setTimeout(() => {//此时的this指向的是声明函数下的this adthis.style.background = 'skyblue';}.2000);
});

4.2  从数组中返回偶数元素

const arr = [1, 6, 9, 10, 100, 25];
//1、原始写法
const result = arr.filter(function(item) {if(item % 2 === 0 ) {return true;}else {return false;}})
console.log(result);//2、简写
const result = arr.filter (item => item % 2 === 0);
console.log(result);    //Array(3)

5、总结

箭头函数适合于this无关的回调,如:定时器,数组的方法回调。

箭头函数不适合与this 有关的回调,如:dom事件回调,对象的方法。

八、函数参数默认值

ES6允许给函数参数(形参)赋值初始值

1、形参初始值,具有默认的参数,一般位置要靠后

function add(a, b, c = 10) {return a + b + c;}
let result = add(1, 2);
console.log(result);    //1+2+10=13

2、可与解构赋值相结合

function connect ({host,username,password,port}) {console.log(host);console.log(username);console.log(password);console.log(port);}
connect ({host: 'localhost';username;'root';password: 'root';port: 3306})

3、rest参数

ES6 引入rest参数,用于获取函数的实参,用来代替arguments。

rest参数必须要放到参数最后面

function date(...args) {console.log(args);
}
date('白芷', '陈皮', '决明子');   // ['白芷', '陈皮', '决明子']
function fn(a, b, ...args) {console.log(a);      //1console.log(b);      //2console.log(args);   //[3, 4, 5, 6]
}fn(1, 2, 3, 4, 5, 6); 

九、扩展运算符

1、语法结构

【...】 扩展运算符能够将数组转行为逗号分隔的参数序列

const tyboys = ['易烊千玺', '王源', '王俊凯']; // => '易烊千玺', '王源', '王俊凯'
function chunwan (){console.log(arguments);
}
chunwan(...tfboys);  //等同于 chunwan('易烊千玺', '王源', '王俊凯')

2、扩展运算符的运用

2.1 数组的合并

const kuaizi = ['王太利', '肖央'];
const fenghuang = ['曾毅', '玲花'];
const zuixuanxiaopingguo = [...kuaizi,...fenghuang];
console.log(zuixuanxiaopingguo);

2.2 数组的克隆(引用类型数据,浅拷贝)

const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];
console.log(sanyecao);

2.3 将伪数组转为真正的数组

const divs = document.querySelectorAll('div');
const divArr = [...divs];console.log(divArr);

十、Symbol

1、Symbol的基本使用

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。

拓展:JavaScript语言的第七种数据类型     USONB

U:  undefined

S: string  symbol

O:  object

N:  null   number

B: boolean

1.1 Symbol的特点

(1)Symbol的值是唯一的,用来解决命名冲突的问题

let s = Symbol();
console.log(s, typeof s);
let s2 = Symbol('王者荣耀');
let s3 = Symbol('王者荣耀');
console.log(s2 === s3); /* false */

(2)Symbol值不能与其他数据进行运算

(3)Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名。

let s4 = Symbol.for('王者荣耀');
let s5 = Symbol.for('王者荣耀');
console.log(s4 === s5); /* true */

1.2  Symbol创建对象属性

let game = {name: '俄罗斯方块',up: function() {},down: function() {}};
//声明一个对象
let methods = {up : Symbol(),down : Symbol()};
game[methods.up] = function(){console.log('我可以改变形状');}
game[methods.down] = function(){console.log('我可以快速下降');}
console.log(game);    //{name: '俄罗斯方块', up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}
let youxi = {name:'狼人杀',[Symbol('say')]:function(){console.log('我可以发言');},[Symbol('zibao')]:function(){console.log('我可以自爆');}};
console.log(youxi);       //{name: '狼人杀', Symbol(say): ƒ, Symbol(zibao): ƒ}

2、Symbol的内置值

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,只想语言内部使用的方法。

Symbol.hasInstance 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpeadble 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype,concat()时,是否可以展开。
Symbol.unscopables 该对象指定了使用with关键字时,哪些属性会被with环境排除。
Symbol.match 当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。
Symbol.replace 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值。
Symbol.search 当该对象被str.search(myObject)方法调用时,会返回该方法的返回值。
Symbol.split 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值。
Symbol.iterator 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器。
Symbol.toPrimitive 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol.toStringTag 在该对象上面调用toString方法时,返回该方法的返回值
Symbol.species 创建衍生对象时,会使用该属性。
//1、Symbol.hasInstance
class Person {static[Symbol.hasInstance]() {console.log('我被用来检测类型了');}}
let o = {};
console.log(o instanceof Person);    //false//2、Symbol.isConcatSpeadble
const arr = [1, 2];
const arr2 = [3, 4, 5];
arr2[Symbol.isConcatSpreadable] = false;   //如果设置为false,则代表数组不可展开
console.log(arr.concat(arr2));             //[1, 2, Array(3)]

十一、迭代器

迭代器(Iterator)是一种接口,为各种不同的数据结构提供同意的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作。

(1)ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费

(2)原生具备iterator接口的数据(可用for of遍历)

Array     Arguments    Set    Map    String   TypeArray    NodeList

(3)工作原理:

① 创建一个指针对象,指向当前数据结构的起始位置

② 第一次调用对象的next方法,指针自动指向数据结构的第一个成员

③ 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员

④ 每调用next方法返回一个包含value和done属性的对象

注:需要自定义遍历数据的时候,要想到迭代器。

const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
//使用for..of 遍历
//for...of 保存的是键值(遍历数组)    for...in 保存的是键名(遍历对象、数组)/*for (let v of xiyou){console.log(v);}*/let iterator = xiyou[Symbol.iterator]();//调用对象的next方法
console.log(iterator.next());    //{value: '唐僧', done: false}
console.log(iterator.next());    //{value: '孙悟空', done: false}
console.log(iterator.next());    //{value: '猪八戒', done: false}
console.log(iterator.next());    //{value: '沙僧', done: false}
console.log(iterator.next());    //{value: undefined, done: true}
//迭代器应用-自定义遍历数组
const banji = {name:"终极一班",stus: ['xiaoming','xiaoning','xiaotian','knight'],[Symbol.iterator](){//索引变量let index = 0;let _this = this;return {next:function(){if (index < _this.stus.length) {const result = {value:_this.stus[index],done:false};//下标自增index++;return result;}else {return {value:undefined;done:true}}}};}}
//遍历这个对象,使用for...of遍历,返回的是这个属性数组里的每一个成员
for (let v of banji) {console.log(v);}

十二、生成器

生成器是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同

生成器是一种特殊的函数,来进行异步编程

function * gen(){//yield作为函数代码的分隔符,三个分隔符产生四个代码yield '一只没有耳朵';yield '一只没有尾巴';yield '真奇怪';
}
for (let v of gen){console.log(v);}
function * gen (arg) {console.log(arg);           //AAAlet one = yield 111;console.log(one);           //BBBlet two = yield 222;console.log(two);           //CCClet three = yield 333;console.log(three);         //DDD}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(itrator.next());             //{value: 111, done: false}
//next方法可以传入实参
console.log(itrator.next('BBB'));        //{value: 222, done: false}
console.log(itrator.next('CCC'));        //{value: 333, done: false}
console.log(itrator.next('DDD'));        //{value: undefined, done: true}

生成器实例

1、回调地狱

//1s 后控制台输出 111   2s后输出222   3s后输出333
setTimeout(() => {console.log(111);setTimeout(() => {console.log(222);setTimeout(() => {console.log(333);},3000);},2000);},1000);
function one() {setTimeout(() => {console.log(111);iterator.next();},1000)
}
function two() {setTimeout(() => {console.log(222);iterator.next();},2000)
}
function three() {setTimeout(() => {console.log(333);iterator.next();},3000)
}
function * gen() {yield one();yield two();yield three();
}//调用生成器函数
let iterator = gen();
iterator.next();

2、 模拟获取

//模拟获取 用户数据 订单数据 商品数据
//先后顺序,依次获取function getUsers() {setTimeout(() => {let data = '用户数据';//调用next方法,并且将数据传入iterator.next(data);}, 1000);
}function getOrders() {setTimeout(() => {let data = '订单数据';iterator.next(data);}, 1000);
}function getGoods() {setTimeout(() => {let data = '商品数据';iterator.next(data);}, 1000);
}function* gen() {let users = yield getUsers();console.log(users);let orders = yield getOrders();console.log(orders);let goods = yield getGoods();console.log(goods);
}//调用生成器函数
let iterator = gen();
iterator.next();

十三、Promise(面试常问)

1、基础

1. 1区别实例对象与函数对象

① 实例对象:new函数产生的对象,称为实例对象,简称为对象

② 函数对象:将函数作为对象使用时,称为函数对象

//括号的左边的函数, 点的左边是对象function Fn() {                 //Fn是函数const fn = new Fn()        //此时Fn是构造函数   fn是实例对象,简称为对象console.log(Fn.prototype)  //Fn是函数对象Fn.blind({})               //Fn是函数对象$('#text')                 //jQuery函数$.get('/test')             //jQuery函数对象
}  

1. 2 两种类型的回调函数

   1.2.1  同步回调

                   概念:立即执行,完全执行完了才结束,不会放入回调队列中

例子:数组遍历相关的回调函数/Promise的excutor函数

const arr = [1, 3, 5]
arr.forEach(item => {console.log(item);            //遍历的回调,同步回调函数,不会放入队列,一上来就要执行完
})
console.log('forEach()之后');

           1.2.2  异步回调

概念:不会立即执行,会放入回调队列中将来执行

例子:定时器回调、Ajax回调、Promise的成功|失败的回调

setTimeout(() => {console.log('timeout callback()');        //异步回调函数,会放入队列中将来执行
}, 0);
console.log('setTimeout()之后');

1.3  JS的error处理

1.3.1 错误的类型

① Error:所有错误的父类型

② ReferenceError:引用的变量不存在

③ TypeError:数据类型不正确的错误

④ RangError:数据值不在其所允许的范围内

⑤ SyntaxError:语法错误

1.3.2 错误处理

① 捕获错误:try...catch

try {let bconsole.log(b.xxx);} catch (error) {console.log(error); //TypeError: Cannot read properties of undefined (reading 'xxx')}

② 抛出错误:throw error

 function something() {if (Date.now() % 2 === 1) {console.log('当前的时间为奇数,可以执行任务');} else { //抛出异常,由调用者来处理throw new Error('当前时间为偶数,无法执行任务')}}//捕获处理异常
try {something()} catch (error) {alert(error.message)}

2、 promise的理解和使用

2.1   Promise是什么

① 抽象表达:Promise是JS中进行异步编程的新的解决方案(旧的是纯回调形式)

② 具体表达:

(1)从语法上来说:Promise是一个构造函数

(2)从功能上来说:Promise对象用来封装一个异步操作并可以获取其结果

2.2   Promise的状态改变

① pendding变为resolved

② pedding变为rejected

说明:只有这2种,且一个promise对象只能改变一次

无论变为成功还是失败,都会有一个结果数据

成功的结果数据一般称为value,失败的结果数据一般称为reason

2.3   Promise的基本流程

2.4   Promise的基本使用

//1、创建一个新的promise对象const p = new Promise((resolve, reject) => { //执行器函数//2、执行异步操作任务setTimeout(() => {const time = Date.now() //如果当前时间是偶数,就代表成功,否则代表失败// 3、(1)如果成功了,调用resolve(value)if (time % 2 == 0) {resolve('成功的数据, time =' + time)} else {//    (2)如果失败了,调用rejecte(reason)reject('失败的数据,time' + time)}}, 1000);})//4、p.then(value => { //接收得到成功的value数据      onResolvedconsole.log('成功的回调', value);},reason => { //接收得到失败的reason数据   onRejectedconsole.log('失败的回调', reason);})

2.5   为什么要用Promise ?

① 使指定回调函数的方式更加灵活

(1)旧的:必须在启动异步任务前指定

(2)promise:启动异步任务  => 返回promise对象  => 给promise对象绑定回调函数 (甚至可以在异步任务启动后就指定)

// 1.1使用纯回调函数createAudioFileAsync(audioSettings, successCallback, failureCallback)
// 1.2使用promiseconst promise = createAudioFileAsync(audioSettings);setTimeout(() => {promise.then(successCallback, failureCallback);}, 3000);

② 支持链式调用,可以解决回调地狱的问题

(1)什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件(内层的结果为外层的参数)

(2)回调函数的缺点?不便于阅读/不便于异常处理

(3) 解决方案?promise链式调用

(4)终极解决方案?async/await

//2.1回调地狱doSomething(function(result) {doSomethingElse(result, function(newResult) {doThirdThing(newResult, function(finalResult) {console.log('Got the final result' + finalResult);}, failureCallback)}, failureCallback)}, failureCallback)//2.2  使用promise的链式调用解决回调地狱doSomething().then(function(result) {return doSomethingElse(result)}).then(function(newResult) {return doThirdThing(newResult)}).then(function(finalResult) {lconsole.log('Got the final result' + finalResult)}).catch(failureCallback) //异常传透//2.3  async/await :回调地狱的终极解决方案asnycfunction request() {try {const result = await doSomething();const newResult = await doSomethingElse(result);const finalResult = await doThirdThing(newResult);console.log('Got the final result' + finalResult)} catch (error) {failureCallback(error)}}

2.6   如何使用Promise ?

2.6.1 API

一、Promise构造函数:Promise(excutor){ }

(1)excutor函数:执行器(resolve,reject)=> { }

(2)resolve函数:内部定义成功时我们调用的函数value =>{ }

(3)reject函数:内部定义失败时我们调用的函数 reason =>{ }

说明:excutor会在Promise内部立即同步回调,一步操作在执行器中执行

二、Promise.prototype.then方法:(onResolved,onRejected)=>{ }

onResolved函数:成功回调函数   (value)=> { }

onRejected函数:失败回调函数   (reason)=> { }

说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调

返回一个新的promise对象

三、Promise.prototype.catch方法:(onRejected)=> { }

onRejected函数:失败的回调函数 (reason)=> { }

说明:then()的语法糖,相当于:then(undefined,onRejected)

四、Promise.resolve方法:(value)=> { }

value:成功的数据或promise对象

说明:返回一个成功/失败的promise对象

五、Promise.reject方法:(reason)=> { }

reason:失败的原因

说明:返回一个失败的promise对象

new Promise((resolve, reject) => {setTimeout(() => {resolve('成功的数据')//只能执行一次reject('失败的数据')}, 1000)}).then(value => {console.log('onResolved()1', value);}).catch(reason => {console.log('onRejected()', reason);})
 const p1 = new Promise((resolve, reject) => {resolve(1)})const p2 = Promise.resolve(2);const p3 = Promise.reject(3);p1.then(value => {console.log(value)})p2.then(value => {console.log(value)})p3.catch(reason => {console.log(reason)})

2.6.2 Promise的几个关键问题

              一、如何改变Promise的状态?

(1)resolve(value):如果当前是pendding就会变为resolved

(2)reject(reason):如果当前是pendding就会变为rejectd

(3)抛出异常:如果当前是pendding就会变为rejectd

 const p = new Promise((resolve, reject) => {// resolve(1) //promise变为resolved状态// reject(2) //promise变为rejected状态// throw new Error('出错了') //抛出异常,promise变为rejected失败状态,reason抛出的errorthrow 3})p.then(value => {},reason => {console.log('reason', reason); // 'reason', 3})

二、一个Promise指定多个成功/失败回调函数,都会调用嘛?

当Promise改变为对应状态时都会调用

三、改变Promise状态和指定回调函数谁先谁后?

(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调

(2)如何先改状态再指定回调?

① 在执行器中直接调用resolve()/ reject()

② 延迟更长时间才能调用then()

(3)什么时候才能得到数据?

① 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

② 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据

 //1、常规:先执行回调函数,后改变状态new Promise((resolve, reject) => {setTimeout(() => {resolve(1) //后改变状态(同时指定数据),异步执行回调函数}, 1000);}).then( //先指定回调函数,保存当前指定的回调函数value => {},reason => {console.log('reason', reason);})//2、先改状态,后执行回调函数new Promise((resolve, reject) => {resolve(1) //先改变状态(同时指定数据)}).then( //后指定回调函数,异步执行回调函数value => {console.log('value', value);},reason => {console.log('reason', reason);})

四、Promise.then()返回的新的Promise的结果状态由什么决定?

(1)简单表述:由then()指定的回调函数执行的结果决定

(2)详细表述:

① 如果抛出异常,新Promise变为rejected,reason为抛出的异常

② 如果返回的是非Promise的任意值,新Promise变为resolved,value为返回的值

③ 如果返回的是另一个新Promise,此Promise的结果就会成为新Promise的结果

五、Promise如何串连多个操作任务

(1)Promise的then()返回一个新的Promise,可以开成then()的链式调用

(2)通过then的链式调用串连多个同步/异步任务

六、Promise异常传透

(1)当使用Promise的then链式调用时,可以在最后指定失败的回调

(2) 前面任何操作出了异常,都会传到最后失败的回调中处理

七、中断Promise链

(1)当使用Promise的then链式调用时,在中间中断,不再调用后面的回调函数

(2)办法:在回调函数中返回一个pendding状态的Promise对象

3、自定义(手写)Promise

3.1 定义整体结构(创建promise.js)

/*
自定义Promise函数模块:IFFE
*/
(function(window) {/*Promise构造函数executor:执行器函数(同步执行)*/function Promise(excutor) {//resolve函数function resolve(data) {}//reject函数function reject (data) {}//同步调用执行器函数executor(resolve,reject);}/*Promise原型对象的then()1.指定成功和失败的回调函数2.函数返回一个新的promise对象*/Promise.prototype.then = function(onResolve, onReject) {}/*Promise原型对象的catch()1.指定失败的回调函数2.函数返回一个新的promise对象*/Promise.prototype.catch = function(onRejectd) {}/*Promise函数对象的resolve方法返回一个指定结果的成功promise*/Promise.resolve = function(value) {}/*Promise函数对象的reject方法返回一个指定结果的失败promise*/Promise.reject = function(reason) {}/*Promise函数对象的all方法返回一个promise,只有当所有promise都成功时,才成功,否则有一个失败,都失败*/Promise.all = function(promises) {}/*Promise函数对象的race方法返回一个promise,其结果由第一个完成的promise来决定*/Promise.race = function(promises) {}//向外暴露promise函数window.Promise = Promise
})(window)

3.2 Promise构造函数的实现

3.3 Promise.then()/ catch()的实现

3.4 Promise.resolve() /  reject()的实现

//添加resolve方法Promise.resolve = function(value) {//返回promise对象return new Promise((resolve, reject) => {if (value instanceof Promise) {value.then(v => {resolve(v);}, r => {reject(r);})} else//状态设置成功、resolve(value)});}//添加reject方法Promise.reject = function(reason) {//返回promise对象return new Promise((resolve, reject) => {reject(reason);});}

3.5 Promise.all()的实现

Promise.all = function(promises) {//返回结果为promise对象return new Promise((resolve, reject) => {//遍历for (let i = 0; i < promises.length; i++) {//声明变量let count = 0;let arr = [];//promises[i].then(v => {//得知对象的状态是成功的//每个promise对象都成功,才能执行resolve函数count++;//将当前promise对象成功的结果存入数组arr[i] = v;//判断if (count === promises.length) {resolve(arr);}}, r => {reject(r);})}});}

3.5 Promise.all / race()的实现

Promise.race = function(promises) {return new Promise((resolve,reject)=>{for(let i = 0 ; i < promises.length;i++){promises[i].then(v=>{//修改返回对象值为成功resolve(v);},r=>{//次该范湖对象为失败reject(r);})}});}

4、async与await

4.1 async函数

(1)函数的返回值为promise对象

(2)promise对象的结果由async函数执行的返回值决定

//和then返回规则一样async function main() {//1、如果返回值是一个非promise类型的数据//  return 521;//2、如果返回值是一个promise对象return new Promise((resolve, reject) => {// resolve('ok');reject('error');})//3、抛出异常throw "oh no";};let result = main();console.log(result);

4.2 await表达式

(1)await右侧的表达式一般为promise对象,但也可以是其他的值

(2)如果表达式是promise对象,await返回的是promise成功的值

(3)如果表达式是其他值,直接将此值作为await的值

注意:

(1)await必须写在async函数中,但async函数中可以没有await

(2)如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理

//await必须写在async函数中,但async函数中可以没有await// await 10; //Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modulesasync function main() {let p = new Promise((resolve, reject) => {// resolve('ok');reject('error');});//1、右侧为promise的情况// await返回值是promise成功的值let res = await p;console.log(res); //ok//2、右侧为其他类型的数据//直接将此值作为await的值let res2 = await 20;console.log(res2); //20//3、如果promise是失败的状态try {let res3 = await p;} catch (e) {console.log(e);  //error}}main();

十四、Set

ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for...of进行遍历,集合的属性和方法:

(1)size   返回集合的元素个数

(2)add   增加一个新元素,返回当前集合

(3)delete 删除元素,返回boolean值

(4)has  检测集合中是否包含某个元素,返回boolean值。

//声明一个setlet s = new Set();let s2 = new Set(['大事', '小事', '没事']);console.log(s, typeof s); //Set(0) {size: 0}[[Entries]]无属性size: 0[[Prototype]]: Set 'object'console.log(s2, typeof s2); //Set(3) {'大事', '小事', '没事'} 'object'//1、元素个数console.log(s2.size); //3//添加新的元素s2.add('喜事');console.log(s2); //Set(4) {'大事', '小事', '没事', '喜事'}//删除元素s2.delete('喜事');console.log(s2);//2、检测console.log(s2.has('大事')); //true//3、清空s2.clear();console.log(s2); //Set(0) {size: 0}//遍历for (let v of s2) {  console.log(v);}

案例:

   let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];//1、数组去重let result = [...new Set(arr)];console.log(result);//2、交集let arr2 = [4, 5, 6, 5, 6];//filter创建一个数组,符合条件的都放进去(过滤器)let result = [...new Set(arr)].filter(item => {let s2 = new Set(arr2);  //4.5.6if(s2.has(item)){return true;}else {return false;}}); //简写let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));console.log(result); //[4,5]//3、并集let union = [...new Set([...arr, ...arr2])];console.log(union);   //合并arr和arr2数组   [1, 2, 3, 4, 5, 6]//4、差集//用arr和arr2比较let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));  

十五、Map

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。Map也实现了iterator接口,所以可以使用扩展运算符和for...of进行遍历。Map的属性和方法:

(1)size  返回Map的元素个数

(2)set   增加一个新元素,返回当前Map

(3)get   返回键名对象的键值

(4)has   检测Map中是否包含某个元素,返回Boolean值

(5)clear  清空集合,返回undefined

十六、class类

function Phone() {}// Phone是函数对象,属于类,不属于实例对象Phone.name = '手机';Phone.change = function() {console.log('我可以改变世界');}Phone.prototype.size = '5.5inch';//nokia是实例对象let nokia = new Phone();console.log(nokia.name); //undefinedconsole.log(nokia.size); //5.5inch
class Phone {//静态属性  static标注的属性和方法,属于class类,不属于实例对象vivostatic name = '手机';static change() {console.log('手机真好玩');}}let vivo = new Phone();console.log(vivo.name); //undefinedconsole.log(Phone.name); //手机

十七、数值扩展

1、Number.EPSILON是JavaScript表示的最小精度

EPSILON属性的值接近于2.2204460492503130808472633361816E-16(主要用作在浮点数上)

function equal(a, b) {if (Math.abs(a - b) < Number.EPSILON) {return true;} else {return false;}}console.log(0.1 + 0.2 === 0.3);      //falseconsole.log(equal(0.1 + 0.2, 0.3));  //true

2、二进制和八进制

let b = 0b1010; //二进制let o = 0o777; //八进制let d = 100; //十进制let x = 0xff; //十六进制console.log(b); //10console.log(d); //100

3、Number.inFinite 检测一个数值是否为有限数

console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100 / 0)); //false
console.log(Number.isFinite(Infinity));//false

4、Number.isNaN 检测一个数值是否为NaN

console.log(Number.isNaN(123)); //false

5、Number.parseInt / Number.parseFloat字符串转整数

 console.log(Number.parseInt('5201314love')); //5201314console.log(Number.parseFloat('3.1415926神奇'));//3.1415926

6、Number.isInteger 判断一个数是否为整数

console.log(Number.isInteger(5));   //true
console.log(Number.isInteger(2.55));//false

7、Math.trunc 将数字的小数部分抹掉

console.log(Math.trunc(3.5)); //3

8、Math.sign 判断一个数到底为正数、负数还是零

console.log(Math.sign(100));  //1
console.log(Math.sign(0));    //0
console.log(Math.sign(-250));  //-1

十八、对象扩展

1、Object.is 判断两个值是否完全相等

 console.log(Object.is(120, 121)); //作用和===很像console.log(Object.is(NaN, NaN)); //trueconsole.log(NaN === NaN); //false  

2、Object.assign对象的合并

const config1 = {hose: 'localhost',port: 3306,name: 'root',pass: 'root',text: 'test',};const config2 = {host: 'http://baidu.com',port: 33060,name: 'baidu',pass: 'iloveyou'};console.log(Object.assign(config1, config2));//{hose: 'localhost', port: 33060, name: 'baidu', pass: 'iloveyou', text: 'test', …}// hose: "localhost"// host: "http://baidu.com"// name: "baidu"// pass: "iloveyou"// port: 33060// text: "test"// [[Prototype]]: Object

3、Object.setPrototypeOf  / Object.getPrototypeOf

const school = {name: 'beida'};
const city = {xiaoqu: ['北京', '上海', '深圳']};
Object.setPrototypeOf(school, city);
console.log(Object.getPrototypeOf(school));   //{xiaoqu: Array(3)}
console.log(school);   //{name: 'beida'}

十九、模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

1、模块化的好处

(1)防止命名冲突

(2)代码复用

(3)高维护性

2、模块化规模产品

ES6之前的模块化规范有:

(1)CommonJs    =>    NodeJs、Browserify

(2)AMD              =>    requireJS

(3)CMD             =>   seaJS

3、ES6模块化语法

模块功能主要由两个命令构成:export和import

(1)export命令用于规定模块的对外接口

(2)import命令用于输入其他模块提供的功能

ECAMScript6基础知识相关推荐

  1. 嵌入式Linux的OTA更新,基础知识和实现

    嵌入式Linux的OTA更新,基础知识和实现 OTA updates for Embedded Linux, Fundamentals and implementation 更新的需要 一旦嵌入式Li ...

  2. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  3. 嵌入式linux编程,嵌入式Linux学习笔记 - 嵌入式Linux基础知识和开发环境的构建_Linux编程_Linux公社-Linux系统门户网站...

    注:所有内容基于友善之臂Mini2440开发板 一.嵌入式Linux开发环境的构建 嵌入式开发一般分为三个步骤: 1.编译bootloader,烧到开发板 2.编译嵌入式Linux内核,烧到开发板 3 ...

  4. 《计算机网络应用基础》模拟试卷(六),《计算机与网络应用基础知识1》模拟试卷...

    <计算机与网络应用基础知识1>模拟试卷 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 <计算机与网络应用基础知识1& ...

  5. python向量计算库教程_NumPy库入门教程:基础知识总结

    原标题:NumPy库入门教程:基础知识总结 视学算法 | 作者 知乎专栏 | 来源 numpy可以说是 Python运用于人工智能和科学计算的一个重要基础,近段时间恰好学习了numpy,pandas, ...

  6. python常用变量名_python基础知识整理

    Python Python开发 Python语言 python基础知识整理 序言:本文简单介绍python基础知识的一些重要知识点,用于总结复习,每个知识点的具体用法会在后面的博客中一一补充程序: 一 ...

  7. 计算机基础知识掌握欠缺,《计算机基础知识》实验教学改革探讨.pdf

    <计算机基础知识>实验教学改革探讨.pdf Science& TechnologyVision 科 技 视 界 科技 探·索·争鸣 计<算机基础知识>实验教学改革探讨 ...

  8. python计算wav的语谱图_Python实现电脑录音(含音频基础知识讲解)

    前言 今天开始进入近期系列文章的第一篇,如何用 Python 来实现录音功能. 在开始"造轮子"之前,个人一直强调一个观点,如果有些东西已经有了,不妨直接去 github 上搜,用 ...

  9. 计算机wrod初级考试题及答案,计算机基础知识+Word基础知识+Excel基础知识试题答案解析.doc...

    文档介绍: 计算机基础知识+ Word基础知识+ Excel基础知识 第一部分 一.单项选择题 1.世界上第一台电子数字计算机取名为(    ). A.UNIVAC    B.EDSAC    C.E ...

最新文章

  1. 最短路径dijkstra
  2. 记一次Nacos的issue修复之并发导致的NPE异常
  3. DNS服务器详解--------基础篇
  4. python笔试题(1)
  5. 客户关系管理系统-帮管客CRM客户管理系统 v3.0.1
  6. 数学物理方法pdf_中考状元笔记九科(语文+数学+物理+化学+英语+历史+地理+政治+生物)(高清PDF);...
  7. Bootstrap:弹出框和提示框效果以及代码展示
  8. system.data oracleClient 需要Oracle客户端8.1.7或high
  9. 荒芜的周六-PHP之面向对象(三)
  10. BZOJ4152 AMPPZ2014 The Captain 【最短路】【贪心】*
  11. 【路径规划】基于NSGA2实现无人机三维路径规划matlab源码
  12. vs2013 Matlab 2018 (64)混合编程
  13. 离散数学_命题逻辑_部分习题
  14. python单例模式例子_python单例模式实例分析
  15. python SMTP发送带图片的邮件时,报TypeError: Could not guess image MIME subtype错误的解决办法
  16. HbuilderX连接Nox(夜神模拟器)
  17. mybatis-plus过滤不查询某一字段
  18. ebs查看服务状态_监控您的卷状态 - Amazon Elastic Compute Cloud
  19. JAVA-国密算法SM3和SM4应用Example
  20. android+实现微信对话框样式,实现微信对话框的图片样式以及图片边框

热门文章

  1. c++实现图书管理系统v2.0
  2. JS判断ios系统的版本号
  3. edg击败we视频_edg击败we视频_LPL夏季赛:EDG零封V5获三连胜 OMG2-1击败WE
  4. Project2016创建WBS并且进行相关设置
  5. 2021鹏业安装算量软件常见问题整理(二十)
  6. 计算机类专业英文缩写,计算机专业英文缩写词汇汇总
  7. secureCRT无法输入
  8. 屏山计算机学校,四川省屏山县职业技术学校计算机应用专业好吗
  9. <el-tabs>改变样式(去掉下划线及其他样式)
  10. s型增长的matlab曲线图,matlab拟合s型曲线