ES6(ECMAScript6)-ES11 从入门到修仙
ES6:ECMAScript6
一、ES6新特性
1.let变量声明以及声明特性
1.1 let
let 关键字用来声明变量,使用 let 声明的变量有以下几个特点:
let a;
let b,c,d;
let e = 100;
let f = 521,g= 'iloveyou',h = [];
1.变量不能重复声明
let star = '离歌笑';
let star = '李逍遥';
2.块级作用域 全局,函数,eval
//if else while for
{let girl = '赵灵儿';
}
console.log(girl);
3.不存在变量提升
console.log(song);
let song = '仙剑奇侠传';
4.不影响作用域链
{let school = '仙一';function fn(){console.log(school);}fn();
}
1.2案例
需求:点击div更换背景颜色
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div style="width: 50px;height: 50px; margin: 10px; border: 1px solid black; "></div><div style="width: 50px;height: 50px; margin: 10px; border: 1px solid green; "></div><div style="width: 50px;height: 50px; margin: 10px; border: 1px solid yellow;"></div>
</body>
<script>//获取div元素对象let items = document.querySelectorAll("div");for(let i = 0;i<items.length;i++){items[i].onclick = function(){items[i].style.backgroundColor = 'pink';} }console.log(windows.i) //3 // 当var=3的时候,点击事件开始向外层作用域找,找不到,就是windows.i,此时是3,如果是let i,具有块级作用域,所以每一次触碰事件的i都是不同的。
</script>
</html>
1.3const
const
关键字用来声明常量
,const 声明有以下特点:
(常量的含义是指向的对象不能修改
,但是可以改变对象内部的属性
)
1.一定要赋初始值
const A;
2.一般变量使用大写(潜规则)
const a = 100;
3.常量的值不能修改
SCHOOL = 'LIGEXIAO';
4.块级作用域
{const PLAYER = 'UZI';
}
console.log(PLAYER);
5.对于数组和对象的元素修改,不算做对常量的修改,不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];TEAM.push('LGX');console.log(TEAM);
6.不允许重复声明
const FRUIT = "apple"
const FRUIT = "apple" // 报错,不可重复声明
1.4解构赋值
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
使用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式;
1.数组的结构
const F4 = ['李逍遥','林月如','赵灵儿','刘晋元'];
let[li,lin,zhao,liu] = F4;
console.log(li);
console.log(lin);
console.log(zhao);
console.log(liu);
2.对象的解构
const li = {name:'离歌笑',age:'18',sing:function(){console.log('六月的雨');}
}
let{name,age,sing} = li;
console.log(name);
console.log(age);
console.log(sing);
sing();
注意:
- 在let{name,age,sing} = li的{ } 中,里面的变量名需要和对象中的属性名相同
- 可以通过
let {sing} = li
只获取里面的sing
方法,之后也是通过sing()
调用
2. 模板字符串
使用一对反引号 ` ` 声明的字符串,特性如下:
1.声明
let str = `一曲离歌笑江湖`;
console.log(str,typeof str);//一曲离歌笑江湖 string
2.里面可以直接使用换行
let str = ` <ul><li>离歌笑</li><li>李逍遥</li><li>赵灵儿</li></ul>`;
console.log(str);
3.变量拼接(替换/插入)
使用
${变量名}
定位插入的元素位置
let name = '离歌笑';
let out = `一曲${name}江湖`;
console.log(out);//一曲离歌笑江湖
3. 对象的简化写法
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁
let name = '离歌笑';
let sing = function(){console.log('一曲离歌啸江湖');
}
原来:
const cos = {name:name,sing:sing,ligexiao:function(){console.log('一曲离歌啸江湖');}
}
ES6:
const cos = {name,sing,ligexiao(){console.log('行如止水,心无旁骛');}
}
4. 箭头函数
ES6允许使用箭头
=>
定义函数
函数声明:
// let fn = function() {
// ...
// }let fn = (a,b) => {return a + b
}
// 调用函数
console.log(fn(2,3)) // 5
1.this是静态的,this始终指向
函数声明时所在作用域下的this的值
function getName(){console.log(this.name);
}
let getName2 = ()=>{console.log(this.name);
}
window.name = '离歌笑';
const school = {name :'LIGEXIAO',
}
//直接调用
getName();//离歌笑
getName2();//离歌笑//call方法调用
getName.call(school);//LIGEXIAO
getName2.call(school);//离歌笑
2.不能作为构造函数实例化对象
let Person =(name,age)=>{this.name = name;this.age = age;
}
let me = new Person('ligexiao','30');
console.log(me);//Uncaught TypeError: Person is not a constructor
3.不能使用arguments
变量
let fn = () =>{console.log(arguments);//Uncaught ReferenceError: arguments is not defined
}
fn(1,2,3);
4.箭头函数的简写
(1) 省略小括号,当形参有且只有一个的时候可以省略小括号。
// let add = (n) => {
// console.log(n + n)
// }
// add(3) // 6// 简写:
let add = n => {console.log(n + n)
}
add(3) // 6
(2) 省略花括号 { },仅当函数语句只有一条语句
时。此时,'return' 也需要省略,结果即是返回值
let pow = n => n * n
console.log(pow(8)) // 64
实践练习
<!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>8.箭头函数练习</title><style>#ad{width: 200px;height: 200px;background:blue;}</style>
</head>
<body><div id="ad"></div><script>let ad = document.querySelector("#ad");//1.改变元素背景颜色ad.addEventListener('click',function(){//定时器setTimeout(()=>{//修改背景颜色this.style.backgroundColor = '#c00';},1000)})//2.从数组中返回偶数的元素const arr =[1,6,9,10,100,25];// const result = arr.filter(function(value){// if(value%2===0)// {// return true;// }// else{// return false;// }// })// const result = arr.filter((value)=>{// if(value%2===0)// {// return true;// }// else{// return false;// }// })// const result = arr.filter(value=>value%2===0);// console.log(result);//[6, 10, 100]//箭头函数适合与this无关的回调、定时器、数组的方法回调//箭头函数不适合与this有关的回调,事件回调,对象的方法// {// name:'离歌笑',// getName:()=>{// this.name;// }// }</script>
</body>
</html>
箭头函数适合与this无关的回调、定时器、数组的方法回调
箭头函数不适合与this有关的回调,事件回调,对象的方法
5. 函数参数默认值
ES6允许给函数参数赋值初始值
特性:
- 可以给形参赋初始值,一般位置要靠后(潜规则)
function add(a,b,c=12){return a+b+c;
}
let result = add (1,2)
console.log(result) // 15
如果上面代码没有给
形参c
赋初始值,则执行add (1,2)
时,形参c
没有对应的参数,默认为NaN
,所以add (1,2)
的执行结果为NaN
2.与解构赋值结合
function ap({host='127.0.0.1', username, password, port}){console.log(host,username,password,port) //
}
ap({host: 'localhost',username:'admin',password:'000000',port:3000})// 执行结果:localhost admin 000000 3000
6. rest参数
ES6引入
rest参数
,用于获取函数的实参,用来代替arguments
rest参数:以
...
为前缀,例如下面的...args
原来的arguments
function date(){console.log(arguments);
}
date('离歌笑','李逍遥','赵灵儿');//Arguments(3) ['离歌笑', '李逍遥', '赵灵儿', callee: ƒ, Symbol(Symbol.iterator): ƒ]
现在的rest参数
function date(...arg){console.log(arg);
}
date('离歌笑','李逍遥','赵灵儿');//['离歌笑', '李逍遥', '赵灵儿']
rest参数必须要放到参数最后
function fn(a,b,...arg){console.log(a);console.log(b);console.log(...arg);
}
fn(1,2,3,4,5,6,7);//1 // 2//3 4 5 6 7
7. 扩展运算符
扩展运算符
...
,能将数组
转换为逗号分隔的参数序列
const tfboys=['易烊千玺','王源','王俊凯']
function show(){console.log(arguments)
}
show(tfboys) // 一个参数,数组:['易烊千玺', '王源', '王俊凯']
show(...tfboys) //0: "易烊千玺" 1: "王源" 2: "王俊凯"
应用:
1.数组的合并
const arr1 = ['李逍遥','离歌笑'];
const arr2 = ['林月如','赵灵儿'];
// const arr = arr1.concat(arr2);//['李逍遥', '离歌笑', '林月如', '赵灵儿']
const arr = [...arr1,...arr2];
console.log(arr);//['李逍遥', '离歌笑', '林月如', '赵灵儿']
2.数组的克隆
const arr3 = ['李逍遥', '离歌笑', '林月如', '赵灵儿'];
const arr4 = [...arr3];//['李逍遥', '离歌笑', '林月如', '赵灵儿']
console.log(arr4);//['李逍遥', '离歌笑', '林月如', '赵灵儿']
如果数组里面有
引用类型
的数据,则整个为浅拷贝
;否则,就是完全拷贝
const divs = document.querySelectorAll("div");
const divArr = [...divs];
console.log(divArr);// [div, div, div]
8. Symbol
语法
直接使用 Symbol()
创建新的 symbol 类型,并用一个可选的字符串作为其描述。
Symbol([description])
description (可选) 字符串类型。对symbol的描述,可用于调试但不是访问symbol本身。请注意,即使传入两个相同的字符串,得到的 symbol 也不相等。
const symbol1 = Symbol();
const symbol2 = Symbol(42);
Symbol()与Symbol.for()的区别
Symbol() :调用相同的symbol多次,会生成多个symbol
Symbol.for():调用相同的symbol多次,仍只会执行第一次的symbol
Symbol.for(key)
方法会根据给定的键 key
,来从运行时的 symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
key:一个字符串,作为 symbol 注册表中与某 symbol 关联的键(可重复调用)
Symbol.for访问的是一个全局的submbol表,如果有了就访问相应对象,没有就重新创建
Symbol.keyFor()方法:
此方法会获取对应Symbol值的键。
全局定义拿得到symbol的值,普通定义拿不到
let cms = Symbol.for('lgx');//全局定义拿得到symbol的值
console.log(Symbol.keyFor(cms));//lgx
let lxy = Symbol('lxy');//普通定义拿不到
console.log(Symbol.keyFor(lxy));//undefined
原来:(内容相同使用[]读取内容只能读取到第一个)
let user1 = '离歌笑';
let user2 = '离歌笑';
let grade = {[user1]:{js:100,css:89},[user2]:{js:50,css:26}
};
console.log(grade);
现在
// let user1 = '离歌笑';//{js: 100, css: 89}
// let user2 = '离歌笑';
let user1 = {name:'离歌笑',key:Symbol(),
}
let user2 = {name:'离歌笑',key:Symbol(),
}
let grade = {[user1.key]:{js:100,css:89},[user2.key]:{js:50,css:26}
};
console.log(grade[user1.key]);//{js: 100, css: 89}
Symbol取值和赋值都要加[]
私有属性
对象,属性如果不想公布到外部可以用symbol
由于任何两个 symbol 都是不相等的,在 JavaScript 里可以很方便地用来模拟私有属性。symbol` 不会出现在 Object.keys() 的结果中,因此除非你明确地 export 一个 symbol,或者用 Object.getOwnPropertySymbols() 函数获取,否则其他代码无法访问这个属性。
Object.keys()返回属性key,但不包括不可枚举的属性
Reflect.ownKeys()返回所有属性key
let symbol = Symbol("一曲离歌笑江湖");
let lgx = {name:'李逍遥',[symbol]:'离歌笑',
}
// for (const key in lgx)//普通遍历遍历不了symbol的值
// {
// console.log(key);
// }
// for(const key of Object.getOwnPropertySymbols(lgx)){//只能遍历到symbol类型
// console.log(key);
// }
// for(const key of Reflect.ownKeys(lgx))//返回所有属性key
// {
// console.log(key);
// }let site = Symbol('一曲离歌啸江湖');
class User{constructor(name){this.name = name;this[site] = '离歌笑';}getName(){return `${this[site]} ${this.name}`;}
}
let lxy = new User('绿巨人');
// console.log(lxy.getName());
// for(let key in lxy)
// {
// console.log(key);
// }
ES6
引入了一种新的原始数据类型Symbol
,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串
的数据类型。
Symbol的值是唯一的,用来解决命名冲突的问题
Symbol值不能与其他数据进行运算
Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
特性:
- 创建
//创建Symbol
let s = Symbol();
// console.log(s,typeof s);//Symbol() 'symbol'
let s2 = Symbol('离歌笑');
let s3 = Symbol('离歌笑');
console.log(s2===s3);//false
//Symbol.for 创建
let s4 = Symbol.for("离歌笑");
let s5 = Symbol.for("离歌笑");
console.log(s4===s5);//true
2.不能与其他数据进行运算(不可运算、比较)
let result = s+100;
let result = s>100;
let result = s+s;//Uncaught TypeError: Cannot convert a Symbol value to a number
3.数据类型的种类
字符串(String)、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空(Null)、未定义(Undefined),Symbol
应用:
- 给对象添加方法方式一:
let game= {name:'俄罗斯方块',up:function(){console.log('向上');},down:function(){console.log('向下');}
}
//声明一个对象
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(): ƒ}
console.log(game[methods.down]());//我可以快速下降!!!
2.给对象添加方法方式二:
let youxi = {name:'离歌笑',[Symbol('lgx')]:function(){console.log('一曲离歌笑江湖');},[Symbol('lxy')]:function(){console.log('行如止水,心无旁骛');}
}
console.log(youxi);//{name: '离歌笑', Symbol(lgx): ƒ, Symbol(lxy): ƒ}
想读取Symbol方法的内容
let lgx = Symbol('lgx');
let lxy = Symbol('lxy');
let youxi = {name:'离歌笑',lgx:function(){console.log('一曲离歌笑江湖');},lxy:function(){console.log('行如止水,心无旁骛');}
}
youxi.lxy()//行如止水,心无旁骛
symbol 内置属性
1.Symbol.hasInstance(自己控制类型检测)
//自己控制类型检测
class Person{static [Symbol.hasInstance](param){console.log(param);console.log('我被用来检测类型了');return false;}
}
let o = {};
console.log(o instanceof Person);
2.Symbol.isConcatSpreadable(该属性决定了当前对象作为concat的参数时是否可以展开)
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable]=false;
console.log(arr.concat(arr2));
9. 迭代器
迭代器( lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。
ES6创造了一种新的遍历命令for…of循环,lterator接口主要供 for…of消费
原生具备iterator接口的数据(可用for of遍历)
for ... of
和 for ... in
for(let v in xiyou){console.log(v);//0 1 2 3
}
//使用for...of遍历数组
for(let v of xiyou){console.log(v);//李逍遥 赵灵儿 林月如 刘晋元
}
迭代器原理
- 创建一个
指针对象
,指向数据结构的起始位置- 第一次调用
next()
方法,指针自动指向数据结构第一个
成员- 接下来不断调用
next()
,指针一直往后移动,直到指向最后一个
成员- 每次调用
next()
返回一个包含value
和done
属性的对象
const xiyou = ['李逍遥','赵灵儿','林月如','刘晋元'];
//使用for...of遍历数组
// for(let v of xiyou){
// console.log(v);//李逍遥 赵灵儿 林月如 刘晋元
// for in保存的是键名,for of保存的是键值
// }
let iterator = xiyou[Symbol.iterator]();
//调用对象的iterator方法,done: true,指针指向最后一个,结束
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}
done
的值为true
的时候表示循环完成了- 需要自定义遍历数组的时候,要想到迭代器
实践练习
<!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>17.迭代器自定义遍历对象</title>
</head>
<body><script>//声明一个对象const people = {name:'仙剑奇侠传一',stus:['lixiaoyao','zhaolinger','lingyueru','liujingyuan'],[Symbol.iterator](){//索引变量let index = 0;let that = this;return {next:function(){if(index < that.stus.length){const result = {value:that.stus[index],done:false}//下标自增index++;//返回结果return result;}else{return {value:undefined,done:true}}}}}}for(let key of people){console.log(key);}let iterator = people[Symbol.iterator]();console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());</script>
</body>
</html>
10. 生成器
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同,是一种特殊的函数
一个generator看上去像一个函数,但可以返回多次。
generator和函数不同的是,generator由function * 定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次。
回调地狱
setTimeout(()=>{console.log('1秒');setTimeout(()=>{console.log('2秒');setTimeout(()=>{console.log('3秒');setTimeout(()=>{console.log('4秒');setTimeout(()=>{console.log('5秒');},5000)},4000)},3000)},2000)
},1000)
function * generator (){ //函数名和function中间有一个 * yield '耳朵' //yield是函数代码的分隔符yield '尾巴' yield '真奇怪'
}
let iterator = generator()
console.log(iteretor.next())
//{value:'耳朵',done:false} next() // 执行第一段,并且返回yield后面的值
console.log(iteretor.next()) //{value:'尾巴',done:false}
console.log(iteretor.next()) //{value:'真奇怪',done:false}
function * gen(){console.log(111);yield '一只没有耳朵';console.log(222);yield '一只没有眼睛';console.log(333);yield '真奇怪';console.log(444);
}
let iterator = gen();
// iterator.next();//111
// iterator.next();//222
// iterator.next();//333
// iterator.next();//444// console.log(iterator.next());
// console.log(iterator.next());
// console.log(iterator.next());
// console.log(iterator.next());//遍历
for(let v of iterator)
{console.log(v);111 一只没有耳朵 222 一只没有眼睛 333 真奇怪444
}
1. 生成器函数的参数传递
第二次调next方法传入的实参将作为第一个yield语句的整体返回结果
当前next方法传入的实参将作为 上一个yield语句的整体返回结果
function * gen(args){
console.log(args) //AAA
let one = yield 111 //111 (将 yield 111 返回的值赋给one)
console.log(one) //BBB
let two = yield 222 //222
console.log(two) //CCC
let three = yield 333 //333
console.log(three) //DDD
}let iterator = gen('AAA')
console.log(iterator.next())
console.log(iterator.next('BBB')) //next中传入的BBB将作为yield 111的返回结果
console.log(iterator.next('CCC')) //next中传入的CCC将作为yield 222的返回结果
console.log(iterator.next('DDD')) //next中传入的DDD将作为yield 333的返回结果
2. 实例1:用生成器函数的方式解决回调地狱问题
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() //111yield two() //222yield three() /333
}let iterator = gen()
iterator.next()
3.实例2:模拟异步获取数据
异步编程:文件操作 网络操作(ajax,request) 数据库操作 定时器
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){setTimeout(()=>{let data = '用户数据';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();
11. Promise
Promise
是ES6引入的异步编程
的新解决方案。语法上 Promise是一个构造函数,用来封装
异步操作并可以获取其成功
或失败
的结果。
const p = new Promise((resolve, reject) => {setTimeout(()=>{let data='数据库数据'// resolve(data) reject(data) })})p.then(function (value){ // 成功则执行第一个回调函数console.log(value)
},function (reason){ // 失败则执行第二个console.error(reason)
})
Promise读取文件
//1.引入fs模块
const fs = require('fs');
fs.readFile('./resource/content.txt',function(err,data){if(err)throw err;console.log(data);
})const p = new Promise(function(resolve,reject){require('fs').readFile('./resource/content.txt',function(err,data){if(err) reject(err);resolve(data);})
})
p.then(function(value){console.log(value.toString())
},function(reason){console.error('error真成功');
})
Promise封装Ajax请求
//接口地址:https://api.apiopen.top/getJoke
const p = new Promise(function(resolve,reject){//1.创建对象const xhr = new XMLHttpRequest();//2.初始化xhr.open('GET', 'https://api.apiopen.top/geoke');//3.发送xhr.send();//4.绑定事件,处理响应结果xhr.onreadystatechange = function(){//判断if(xhr.readyState === 4){//判断响应状态码 200-299if(xhr.status >= 200 && xhr.status < 300){//表示成功resolve(xhr.response);}else{//表示失败reject(xhr.status);}}}
})
p.then((value)=>{console.log(value);
},
(reason)=>{console.error(reason);
})
Promise.then()
方法
const p =new Promise((resolve, reject) =>{setTimeout(() => {resolve('用户数据') })
});//then()函数返回的实际也是一个Promise对象
//1.当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数的返回值为对象的成功值,如reutnr 123,返回的Promise对象值为123,如果没有返回值,是undefined//2.当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值//3.当回调后,如果抛出的异常,则then()函数的返回值状态也是rejected
let result = p.then(value => {console.log(value)//1.非Promise类型的属性// return 123 //2.是Promise对象// return new Promise((resolve, reject) => {// resolve('ok');// reject('error');//rejected(失败)// })//3.抛出错误// throw new Error('出错啦!');// throw '出错啦!!!';
},reason => {console.log(reason)
})
console.log(result)
链式回调
p.then(value=>{}).then(value=>{})
案例 Promise读取多个文件
//引入fs模块
const fs = require('fs');
//回调地狱
// fs.readFile('./resource/草.txt',(err,data1)=>{
// fs.readFile('./resource/无题.txt',(err,data2)=>{
// fs.readFile('./resource/题雁塔.txt',(err,data3)=>{
// let result = `${data1}
// ${data2}
// ${data3} `;
// console.log(result.toString());
// })
// })
// })
const p = new Promise((reslove,reject)=>{fs.readFile('./resource/草.txt',(err,data)=>{reslove(data);})
})
p.then(value=>{return new Promise((reslove,reject)=>{fs.readFile('./resource/无题.txt',(err,data)=>{reslove([value,data]);})})
}).then(value=>{return new Promise((reslove,reject)=>{fs.readFile('./resource/题雁塔.txt',(err,data)=>{//压入value.push(data);reslove(value);})})
}).then(value=>{console.log(value.join('\r\n'));
})
Promise.catch()
方法
const p = new Promise((resolve, reject) => {setTimeout(()=>{reject('出错啦')},1000)
})p.catch(reason => {console.log(reason)
})
12. 集合
12.1 Set
ES6提供了新的数据结构set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用「扩展运算符』和「 for…of…』进行遍历
集合的属性和方法:
.size
返回集合的元素个数.add()
增加一个新元素,返回当前集合.delete()
删除元素,返回boolean值.has()
检测集合中是否包含某个元素,返回boolean值
let s = new Set();
let s2 = new Set(['A','B','C','D'])//元素个数
console.log(s2.size) //添加新的元素E
s2.add('E') //删除元素A
s2.delete('A')//检测是否有 C
console.log(s2.has('C')) //清空
s2.clear()console.log(s2)
应用:
let arr = [1,2,3,4,5,4,3,2,1];
//1.数组去重
// let result = [...new Set(arr)];
// console.log(result);//[1, 2, 3, 4, 5]
//2.交集
let arr2 = [4,5,6,5,6];
let s2 = new Set(arr2);//4 5 6
// let result = [...new Set(arr)].filter(item=>{
// if(s2.has(item))
// {
// return true;
// }
// else{
// return false;
// }
// })
let result = [...new Set(arr)].filter(item=>s2.has(item))
console.log(result);//[4, 5]
//3.并集
let union = [...new Set([...arr,...arr2])];
console.log(union);//[1, 2, 3, 4, 5, 6]
//4.差集
let diff = [...new Set(arr)].filter(item=>!(s2.has(item)))
console.log(diff);// [1, 2, 3]
12.2 Map
ES6提供了
Map数据结构
。它类似于对象,也是键值对的集合
。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map
也实现了iterator
接口,所以可以使用『扩展运算符』和「for…of…』进行遍历。
Map的属性和方法:
.size
获取Map的键值对数量(最外层).set(key,value)
添加键值对.delete(key)
删除键为key的键值对.get(key)
获取键为key的值for...of
遍历里面的每一个键值对
let m = new Map();
//添加元素
m.set('name','离歌笑');
m.set('lgx',function(){console.log('我可以改变世界');
})
let key = {school:'xianyi'
}
m.set(key,['杭州','长安','仙灵']);//size
console.log(m.size);//删除键为name的键值对,会返回修改后的Map集合
// m.delete(key);
m.delete('name');//获取
console.log(m.get('lgx'));
console.log(m.get(key));//清空
// m.clear();console.log(m);
//遍历里面的每一个键值对
for(let v of m)
{console.log(v);
}
13. Class
ES6提供了更接近传统语言的写法,引入了
Class
(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型
的写法更加清晰、更像面向对象编程的语法而已。
//ES5的构造函数
function Phone(brand,price){this.brand = brand;this.price = price;
}
Phone.prototype.call = function(){console.log('我可以打电话');
}
//实例化对象
let Huawei = new Phone('华为','2000');
console.log(Huawei);
Huawei.call();//ES6的构造函数 Class
class iPhone{//构造方法,名字不能修改constructor(brand,price){this.brand = brand;this.price = price;}//方法必须使用该语法,不能使用ES5的对象完整形式call(){console.log('我可以打电话');}
}
let onePlus = new iPhone("1+",1999);
onePlus.call();
console.log(onePlus);
结果:
13.1 静态成员
ES5静态成员
function Phone(){}
Phone.iname='手机';//静态成员,不能被实例化对象调用
Phone.change= function(){console.log("我可以改变世界,但是先要改变自己");
}
Phone.prototype.size = '5.5inch';
let nokia = new Phone();
console.log(Phone.iname);//手机
Phone.change();//我可以改变世界,但是先要改变自己
console.log(nokia.iname);//undefined
console.log(nokia.size);//5.5inch
ES6静态成员
class Phone{// 声明静态成员变量static name = '手机';static change(){console.log("我可以改变世界,但是先要改变自己");}
}
let nokia = new Phone();
console.log(nokia.name);//undefined
console.log(Phone.name);//手机
13.2 构造函数继承
function Phone(brand,price){this.brand = brand;this.price = price;
}
Phone.prototype.call = function(){console.log("我可以打电话");
}
function SmartPhone(brand,price,color,size)
{Phone.call(this,brand,price);this.color = color;this.size = size;
}
SmartPhone.prototype = new Phone();
//如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的原型对象
SmartPhone.constructor = SmartPhone;
SmartPhone.prototype.photo = function(){console.log('我可以拍照');
}
SmartPhone.prototype.playGame = function(){console.log('我可以玩游戏');
}let chuizi = new SmartPhone('chuizi',2499,'黑色','5.5inch');
console.log(chuizi);
结果:
13.3 Class类继承
class Phone{constructor(brand,price){this.brand = brand;this.price = price;}call(){console.log("我可以打电话");}
}
class SmartPhone extends Phone{constructor(brand,price,color,size){super(brand,price);//Phone.call(this,brand,price)this.color = color;this.size = size;}photo(){console.log('我可以拍照');}playGame(){console.log('我可以玩游戏');}
}
let xiaomi = new SmartPhone('小米',1999,'黑色','4.7inch');
console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
结果:
13.4 子类对父类方法的重写
class Phone{constructor(brand,price){this.brand = brand;this.price = price;}call(){console.log("我可以打电话");}
}
class SmartPhone extends Phone{constructor(brand,price,color,size){super(brand,price);//Phone.call(this,brand,price)this.color = color;this.size = size;}photo(){console.log('我可以拍照');}playGame(){console.log('我可以玩游戏');}//重写!!!call(){console.log('我可以视频通话');}
}
let xiaomi = new SmartPhone('小米',1999,'黑色','4.7inch');
console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
结果:
13.5 get和set设置
class Phone{get price(){console.log('价格属性被读取了');return '10000yuan';}set price(newVal){console.log('价格属性被修改了');}
}
//实例化对象
let s = new Phone();
console.log(s.price);//10000yuan
s.price = "free";
结果:
14 数值扩展
// Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-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);//false
console.log(equal(0.1+0.2,0.3));//true//1.二进制和八进制
let b = 0b1010;//10 //2进制
let o = 0o777;//511 //8进制
let d = 100 //100 //10进制
let x = 0xff //255 //16进制
console.log(x);//2.检测一个数是否为有限数
console.log(Number.isFinite(100));//true
console.log(Number.isFinite(100/0));//false
console.log(Number.isFinite(Infinity));//false//3.检测一个数值是否为NaN
console.log(Number.isNaN(123));//false//4.字符串转整数
console.log(Number.parseInt('5454545love'));//5454545
console.log(Number.parseFloat('5.123123神奇'));//5.123123//5.判断是否为整数
console.log(Number.isInteger(5));//true
console.log(Number.isInteger(2.5));//false//6.将小数部分抹除
console.log(Math.trunc(3.5));//3//7.检测一个数到底是正数、负数、还是0
console.log(Math.sign(100));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-20000));//-1
结果:
15.对象方法扩展
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120));//=== //true
console.log(Object.is(isNaN,isNaN));//=== //true
console.log(NaN===NaN);//false//2.Object.assign 对象的合并
const config1={
host:'localhost',
port:'3306',
name:'root',
pass:'root',
test:'test'
}
const config2={
host:'http://xianyi.com',
port:'33060',
name:'xianyi.com',
pass:'lixiaoyao',
}
console.log(Object.assign(config1,config2));//{host: 'http://xianyi.com', port: '33060', name: 'xianyi.com', pass: 'lixiaoyao', test: 'test'}//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name:'离歌笑'
}
const cities = {
renming:['李逍遥','赵灵儿','林月如']
}
Object.setPrototypeOf(school,cities);
console.log(Object.getPrototypeOf(school));//{renming: Array(3)}
console.log(school);//{name: '离歌笑'}
16. 模块化
模块化是指将一个
大的程序文件
,拆分成许多小的文件
,然后将小文件组合起来。
1. 模块化的好处:
- 防止命名冲突
- 代码复用
- 高维护性
- 模块化规范产品
2. ES6之前的模块化规范有:
- CommonJS ====> NodeJS、Browserify
- AMD ====> requireJS
- CMD ====> seaJS
3. 语法:
- 模块功能主要有两个命令构成:
export
和import
export
命令用于规定模块的对外接口import
命令用于输入其他模块提供的功能
16.1 暴露语法
16.1.1.分别暴露
// 下面js代码放在./js/m1.js文件中
//分别暴露
export let school = '离歌笑';
export function teach(){console.log('一曲离歌笑江湖');
}
<!-- html代码 -->
<script type="module">
//引入模块化内容
import * as m1 from "./js/m1.js";
console.log(m1);
</script>
结果:
16.1.2. 统一暴露
let school = '清华大学';
function findjob(){console.log('找工作吧');
}
//统一暴露
export {school, findjob}
<script type="module"> import * as m1 from "./js/m1.js" console.log(m1) console.log(m1.school)m1.findJob()
</script>
结果:
16.1.3. 默认暴露(多变量暴露)
//默认暴露 export default
export default {school:'清华大学',change:function(){console.log('可以改变人的一生!')}
}
<script type="module"> import * as m1 from "./js/m1.js" console.log(m1.default) console.log(m1.default.school)console.log(m1.default.change())
</script>
结果:
16.2 引入语法
16.2.1. 通用导入方式
import * as m1 from "./js/m1.js"
import * as m2 from "./js/m2.js"
import * as m3 from "./js/m3.js"
16.2.2. 解构赋值方式
import {school,teach} from "./js/m1.js";
import {school as s ,findJob} from "./js/m2.js";
import {default as m3} from "./js/m3.js";
console.log(school,teach);
console.log(s,findJob);
console.log(m3);
结果:
16.2.3. 简便形式(只针对默认暴露)
import m3 from "./js/m3.js";
console.log(m3);//{school: '清华大学', change: ƒ}
16.3 模块化方式2
// 下面js代码放在./js/app.js文件中
//入口文件//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";console.log(m1);
console.log(m2);
console.log(m3);
<!-- html代码 -->
<script type="module" src="./js/app.js"></script>
结果:
16.4 bael对es6模块化代码转换
Babel概述:Babel 是一个 JavaScript 编译器;Babel 能够将新的ES规范语法转换成ES5的语法;因为不是所有的浏览器都支持最新的ES规范,所以,一般项目中都需要使用Babel进行转换;步骤:使用Babel转换JS代码——打包成一个文件——使用时引入即可;
步骤
第一步:安装工具babel-cli(命令行工具) babel-preset-env(ES转换工具) browserify(打包工具, 项目中使用的是webpack);
第二步:初始化项目
npm init -y第三步:安装npm i babel-cli babel-preset-env browserify -D第四步:使用babel转换npx babel js(js目录) -d dist/js (转化后的js目录) --presets=babel-preset-env第五步:打包npx browserify dist/js/app.js -o dist/bundle.js第六步:在使用时引入bundle.js<script src="./js/bundle.js" type="module"></script>
//分别暴露
export let school = '离歌笑';
export function teach(){console.log('一曲离歌笑江湖');
}
'use strict';Object.defineProperty(exports, "__esModule", {value: true
});
exports.teach = teach;
//分别暴露
var school = exports.school = '离歌笑';
function teach() {console.log('一曲离歌笑江湖');
}
16.5 ES6模块化引入NPM包
第一步:安装jquery:
npm i jquery
第二步:在app.js使用jquery
//修改背景颜色为粉色
import $ from 'jquery';//const $ = require("jquery");
$('body').css("background","pink");
第三步:重新转换和打包
npx babel js(js目录) -d dist/js (转化后的js目录) --presets=babel-preset-env
npx browserify dist/js/app.js -o dist/bundle.js
二、ES7新特性
1、Array.prototype.includes
概述:Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值;判断数组中是否包含某元素,语法:arr.includes(元素值);
const renming = ['李逍遥','赵灵儿','林月如','刘晋元'];
console.log(renming.includes('李逍遥'));//true
console.log(renming.includes('离歌笑'));//false
2、指数操作符
概述:在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同;幂运算的简化写法,例如:2的10次方:2**10;
//**(指数操作符)
console.log(2**10);//1024
console.log(Math.pow(2,10));//1024
三、ES8的新特性
1、async 和 await
概述:async 和 await 两种语法结合可以让异步代码看起来像同步代码一样;简化异步函数的写法;
3.1.1async函数
概述:1. async 函数的返回值为 promise 对象;2. promise 对象的结果由 async 函数执行的返回值决定;
1.返回的结果不是一个Promise类型的对象,返回的结果就是成功的Promise对象
2.抛出错误,返回的结果是一个失败的Promise
3.返回的结果如果是一个Promise对象,结果成功就是成功,失败就是失败
// async函数
async function fn(){//返回一个字符串// return '离歌笑';//fulfilled//返回的结果不是一个Promise类型的对象,返回的结果就是成功的Promise对象// return; //抛出错误,返回的结果是一个失败的Promise// throw new Error('出错啦!');//返回的结果如果是一个Promise对象return new Promise((resolve,reject)=>{resolve('成功的数据');//fulfilled// reject('失败的数据');//rejected})
}
const result = fn();
// console.log(result);
//调用then方法
result.then(value=>{console.log(value);
},(reason)=>{console.warn(reason);
})
3.1.2await 表达式
概述:1. await 必须写在 async 函数中;2. await 右侧的表达式一般为 promise 对象;3. await 返回的是 promise 成功的值;4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理;
//创建Promise对象
const p = new Promise((resolve,reject)=>{// resolve('成功啦哦哦');reject('失败的原因很复杂');
}) //await 要放在async函数中
async function main(){try{const result = await p;console.log(result);}catch(e){console.log(e);//失败的原因很复杂}
}
//调用函数
main();
3.1.3async 和 await 读取文件
const fs = require('fs');
function readCao(){return new Promise((reslove,reject)=>{fs.readFile('./resource/草.txt',(err,data)=>{if(err){reject(err);}reslove(data);})})
}
function readWuTi(){return new Promise((reslove,reject)=>{fs.readFile('./resource/无题.txt',(err,data)=>{if(err){reject(err);}reslove(data);})})
}
function readTiYanTa(){return new Promise((reslove,reject)=>{fs.readFile('./resource/题雁塔.txt',(err,data)=>{if(err){reject(err);}reslove(data);})})
}async function main(){//文章1try{let cao = await readCao();console.log(cao.toString());}catch(e){console.log(e);}//文章2try{let wuti = await readWuTi();console.log(wuti.toString());}catch(e){console.log(e);}//文章3try{let tiyanta = await readTiYanTa();console.log(tiyanta.toString());}catch(e){console.log(e);}
}
main();
结果:
3.1.4async 和 await 结合发送ajax请求
//发送Ajax请求,返回的结果是Pomise对象
function sendAJAX(url) {return new Promise((resolve,reject)=>{//1.创建对象const xhr = new XMLHttpRequest();//2.初始化xhr.open('GET',url);//3.发送xhr.send();//4.事件绑定xhr.onreadystatechange = ()=>{if(xhr.readyState === 4){if(xhr.status>=200 && xhr.status<300){//成功resolve(xhr.response);}else{//失败reject(xhr.status);}}}})
}//Promise then方法测试
// sendAJAX('https://api.apiopen.top/getJoke').then((value)=>{
// console.log(value);
// },(reason)=>{
// console.log(reason);
// })//使用async与await
async function main(){//发送AJAX请求let result = await sendAJAX('https://api.apiopen.top/getJoke');console.log(result);
}
main();
2、对象方法扩展
Object.values、Object.entries和
Object.getOwnPropertyDescriptors:
1. Object.values()方法:返回一个给定对象的所有可枚举属性值的数组;2. Object.entries()方法:返回一个给定对象自身可遍历属性 [key,value] 的数组; (对象变数组)3. Object.getOwnPropertyDescriptors()该方法:返回指定对象所有自身属性的描述对象;
//声明对象
const school = {name:'离歌笑',cities:['杭州','长安','汴梁'],zhiye:['daxia','taifu','gongzhu']
} //获取对象所有的键
console.log(Object.keys(school));//['name', 'cities', 'zhiye']
//获取对象所有的值
console.log(Object.values(school));//['离歌笑', Array(3), Array(3)]0: "离歌笑"1: (3) ['杭州', '长安', '汴梁']2: (3) ['daxia', 'taifu', 'gongzhu']length: 3[[Prototype]]: Array(0)
//entries
console.log(Object.entries(school));//[Array(2), Array(2), Array(2)]
//创建Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));//['杭州', '长安', '汴梁']//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));//{name: {…}, cities: {…}, zhiye: {…}}const obj = Object.create(null,{name:{//设置值value:'离歌笑',writable:true,//值是否可以重写。true|false 默认为falseconfigurable:true,//目标属性是否可以被删除或是否可以再次修改特特性 true|false 默认为falseenumerable:true,//目标属性是否可以被枚举。true|false 默认为false}
})
结果:
五、ES9 新特性
1、Rest 参数与 spread 扩展运算符
概述:Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了 像数组一样的 rest 参数和扩展运算符;
// Rest参数与spread扩展运算符
// Rest 参数与 spread 扩展运算符在 ES6 中已经引入,
// 不过 ES6 中只针对于数组,在 ES9 中为对象提供了像
// 数组一样的 rest 参数和扩展运算符
function connect({name,age,...user}){console.log(name);console.log(age);console.log(user);
}connect({name:'离歌笑',age:20,price:5000,wuli:10000000
})
const skillOne = {x:'仙风云体术'
}
const skillTwo = {z:'醉仙望月步',a:'爱无限'
}
const skillThree = {q:'七诀剑气'
}
const skillFour = {y:'御剑术'
}const lixiaoyao = {...skillOne,...skillTwo,...skillThree,...skillFour};//对象的合并
console.log(lixiaoyao);//{x: '仙风云体术', z: '醉仙望月步', q: '七诀剑气', y: '御剑术'}
结果:
2、正则扩展:命名捕获分组
概述:ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强;
//声明一个字符串
let str = '<a href="http://baidu.com">离歌笑</a>';//提取url 与[标签文本]
const reg = /<a href="(.*)">(.*)<\/a>///执行
const result = reg.exec(str);
console.log(result[1]);//http://baidu.com
console.log(result[2]);//离歌笑let str1 = '<a href="http://baidu.com">离歌笑</a>';
const reg1 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result1 = reg.exec(str1);
// console.log(result1);
console.log(result1.groups.url);//http://baidu.com
console.log(result1.groups.text);//离歌笑
3、正则扩展:反向断言
概述:ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选;
//声明字符串
let str = 'JS5201314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);//反向断言
const reg1 = /(?<=么)\d+/;
const result1 = reg1.exec(str);
console.log(result1);
4、正则扩展:dotAll 模式
概述:正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行终止符出现;
//dot . 元字符 除换行符以外的任意单个字符
let str = `<ul><li><a>肖生克的救赎</a><p>上映日期: 1994-09-10</p></li><li><a>阿甘正传</a><p>上映日期: 1994-07-06</p></li></ul>
`;//声明正则
// const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p/;
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
// const result = reg.exec(str);
let result;
let data =[];
while(result = reg.exec(str)){data.push({title:result[1],time:result[2]});
}
//输出结果
console.log(data);
结果:
六、ES10 新特性
1、Object.fromEntries
概述:将二维数组或者map转换成对象;之前学的Object.entries是将对象转换成二维数组;
// Object.fromEntries:将二维数组或者map转换成对象
// 之前学的Object.entries是将对象转换成二维数组
// 此方法接收的是一个二维数组,或者是一个map集合
// 二维数组
const result = Object.fromEntries([
['name','离歌笑'],
['city','长安,余杭,仙灵']
]);
console.log(result);//{name: '离歌笑', city: '长安,余杭,仙灵'}
//Map
const m = new Map();
m.set('name','ligexiao')
console.log(m);//Map(1) {'name' => 'ligexiao'}
const result1 = Object.fromEntries(m);
console.log(result1.name);//ligexiao
console.log(result1);//{name: 'ligexiao'}
//Object.entries ES8
const arr = Object.entries({
name:'绿儿'
});
console.log(arr);
结果:
2、trimStart 和 trimEnd
概述:去掉字符串前后的空白字符;
//trim
let str = ' ligexiao ';
console.log(str);// ligexiao
console.log(str.trim());//ligexiao
console.log(str.trimStart());//ligexiao
console.log(str.trimEnd());// ligexiao
结果:
3、Array.prototype.flat 与 flatMap
概述:将多维数组转换成低维数组;
//flat 平
//将多维数组转化为低维数组
// const arr = [1,2,3,[4,5,6]];// [1, 2, 3, 4, 5, 6]
// const arr = [1,2,3,4,[5,6,7,[8,9,0]]];// [1, 2, 3, 4, 5, 6, 7, Array(3)] Array(3):[8, 9, 0]
const arr = [1,2,3,4,[5,6,7,[8,9,0]]];
//参数为深度,是一个数字
console.log(arr.flat(2));// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]//flatMap 将map得出的多维数组转化为低维数组
const arr1 = [1,2,3,4];
const result0 = arr1.map(item=>item * 10);//[10, 20, 30, 40]
const result1 = arr1.map(item=>[item*10]);//Array(1), Array(1), Array(1), Array(1)] -> [10][20][30][40]
const result2 = arr1.flatMap(item=>item * 10);//[10, 20, 30, 40]
console.log(result0);
console.log(result1);
console.log(result2);
结果:
4、Symbol.prototype.description
概述:获取Symbol的描述字符串;
//创建Symbol
let s = Symbol('离歌笑');
console.log(s.description);//离歌笑
七、ES11 新特性
1、String.prototype.matchAll
概述:用来得到正则批量匹配的结果;
let str = `<ul><li><a>肖生克的救赎</a><p>上映日期: 1994-09-10</p></li><li><a>阿甘正传</a><p>上映日期: 1994-07-06</p></li></ul>
`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
//调用方法
const result = str.matchAll(reg);
for(let v of result)
{console.log(v);
}
// const arr = [...result];
// console.log(arr);
结果:
2、类的私有属性
概述:私有属性外部不可访问直接; (可以在内部使用,不能在外部使用)
class Person{//公有属性name;//私有属性#age;#weight;//构造方法constructor(name,age,weight){this.name = name;this.#age = age;this.#weight = weight;}intro(){console.log(this.name);console.log(this.#age);console.log(this.#weight);}
}const girl = new Person('刘亦菲','18','40kg');
console.log(girl);
console.log(girl.name);
console.log(girl.#age);
console.log(girl.#weight);
girl.intro();
3、Promise.allSettled
概述:获取多个promise执行的结果集;
//声明两个Promise对象
const p1 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('商品数据 -1');},1000)
})
const p2 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('商品数据 -2');// reject("出错啦");},1000)
})
//调用allSettled方法
const result = Promise.allSettled([p1,p2]);
console.log(result);
const res = Promise.all([p1,p2]);//两个都为成功才算成功,一个失败则为失败
console.log(res);
结果:
调用allSettled方法
调用all方法
4、可选链操作符
概述:?.如果存在则往下走,省略对对象是否传入的层层判断;
//?.
function main(config)
{const dbHost = config && config.db && config.db.host;console.log(dbHost);//192.168.0.1const cacheHost = config?.cache?.host;console.log(cacheHost);//192.168.0.2
}
main({db:{host:'192.168.0.1',username:'root'},cache:{host:'192.168.0.2',username:'admin',}
})
5、动态 import 导入
概述:
动态导入模块,什么时候使用时候导入;
html页面:
<script type="module" src="./js/app1.js"></script>
<button id="btn">北京欢迎你</button>
app.js:
//静态import
import * as m1 from './hello.js';
const btn = document.getElementById('btn');
btn.onclick = function(){// m1.hello2();//动态importimport('./hello.js').then(module=>{module.hello();})
}
hello.js:
export function hello(){alert('贝贝 晶晶 欢欢 迎迎 妮妮');
}
export function hello2(){alert('贝贝 晶晶 欢欢 迎迎 妮妮2');
}
6、BigInt
概述:更大的整数;
//大整形
let n = 521n;
console.log(n,typeof(n));//521n 'bigint'//函数:普通整形转大整形
let x = 123;
console.log(BigInt(n));//521n
// console.log(BigInt(1.2)); //出错了,BigInt不能用浮点数计算//用于更大数值的运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max);//9007199254740991
console.log(max+1);//9007199254740992
console.log(max+2);//9007199254740992 出错了max+1为最大计算console.log(BigInt(max));//9007199254740991n
console.log(BigInt(max)+BigInt(1));//9007199254740992n
console.log(BigInt(max)+BigInt(2));//9007199254740993n
结果:
7、globalThis 对象
概述:始终指向全局对象window;
console.log(globalThis);
结果:
ES6(ECMAScript6)-ES11 从入门到修仙相关推荐
- 有人把编程写成了修仙小说
很多小伙伴刚开始接触编程的时候,都会觉得学编程非常枯燥,很难入门.但是如果将 编程教材 和 修仙小说 相结合,可能会使你夜不能眠,越学越上瘾! 前两天大雄在线上社群看到有小伙伴分享了两张截图,乍一看还 ...
- 绝了!“修仙模式”学编程是什么体验?
这两天突然有一本书火了,为什么能火? 看看第一章第一节: 不就一修仙小说么,开头也一般般,除了主角名字跟张小凡差个姓之外,也没啥特别啊! 慢着!再仔细看看!什么鬼,JavaScript甲等资质? 原来 ...
- 漫谈架构师之路的修仙之法
从小有一个武侠梦,长大从事了IT,空闲时间看了很多修仙小说.就萌生了一个想法:把IT之路和修仙之路联系到一起. 于是参照<凡人修仙传>的各个修仙阶段,对比IT之路进行了对照,才有了这篇文章 ...
- 2年6个月11天,外包到阿里的修仙之路
前言 估计有同学会有疑问,为什么要精确到天?是为了装逼吗? 答:仅仅是为了证明咱的严谨(其实就是为了装逼) 肯定有同学心里会吐槽:真的是外包吗?估计又是个标题党,吹牛逼,*&¥%¥ 答:真的是 ...
- 2 年 6 个月 11 天,外包到阿里的修仙之路!| 原力计划
作者 | 程序员囧辉 责编 | 王晓曼 出品 | CSDN博客 前言 估计有同学会有疑问,为什么要精确到天?是为了装逼吗? 答:仅仅是为了证明咱的严谨(其实就是为了装逼) 肯定有同学心里会吐槽:真的是 ...
- 大数据生态系统 修仙之道 Hadoop Blog
大数据生态系统 修仙之道 Hadoop Blog @(2019-01-22)[Docs Language:简体中文 & English|Programing Language:Hadoop|W ...
- 程序员的修仙之路-筑基篇
也许很多人都被这个文章的标题吓到.吸引或者迷惑,那我告诉你,这篇文章不是一个程序员的穿越玄幻,不是一个程序员的无聊之谈,里面没有算法公式,亦无程序员的心路历程.它只是一套学习方法与学习工具的使用.这只 ...
- 最强Java修仙之路【附赠BAT修炼资源】,这些核心技能是你必须要掌握的!!
代码尽头谁为峰,一见秃头道成空. 编程修真路破折,一步一劫渡飞升. 众所周知,编程修真有八大境界: Javase-练气筑基 数据库-结丹 web前端-元婴 Javaweb-化神 Javaweb项目-炼 ...
- 前端修仙路-Babel 7.x 详解
前端修仙路-Babel 7.x 详解 前言:Babel 是一个 JavaScript 编译器,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便 ...
最新文章
- 【CSS练习】IT修真院--练习4-移动端界面
- uva 707(记忆化搜索)
- Jquery中正确使用trim方法以及避免遇到坑
- 在驱动和应用程序间共享内存
- (2)MongoDB副本集自动故障转移原理(含客户端)
- C++中的函数汇总(新手必知)!
- [置顶] 状态压缩DP 简单入门题 11题
- 宏定义与预处理、函数和函数库
- shellcraft新姿势
- mysql里面可以用正则吗_Mysql中使用正则表达式
- python 线程(一)理论部分
- cocos2dx 3.x(移动修改精灵坐标MoveTo与MoveBy)
- python 简单的接口测试框架
- 01 牛顿迭代公式
- 用的上的商学课1-50课学习笔记
- html 跑步比赛小游戏,跑步比赛小班游戏教案
- “蔚来杯“2022牛客暑期多校训练营1 J Serval and Essay(图的启发式合并)
- 关系型数据库设计原则
- kali下安装gvm(原openvas)
- STM32CubeMX学习笔记(9)——I2C接口使用(读写EEPROM AT24C02)