ES6-ES11
1、ECMAScript 6
1.1 let 和 const
1.1.1 let 关键字
let关键字用来声明变量,使用let声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
- 不影响作用域链
应用场景:以后声明变量使用let就对了
<div class="item" style="width: 50px;height: 50px;background-color: red"></div>
<div class="item" style="width: 50px;height: 50px;background-color: red"></div>
<div class="item" style="width: 50px;height: 50px;background-color: red"></div>
<script>
let items=document.getElementsByClassName("item");
for (var i=0;i<items.length;i++){
items[i].onclick=function (){
items[i].style.backgroundColor='pink';
}
}
console.log(windows.i) //3
// 相当于
{
var i = 0;
items[i].onclick=function (){
items[i].style.backgroundColor='pink';
}
...
// 最后为每个div添加的点击事件的触发对象都是items[i],这个i就是window.i:3
// 如果用let 就有块级作用域,就不会出现这种情况
}
</script>
1.1.2 const 关键字
const 关键字用来声明常量,const声明有以下特点
- 声明必须赋初始值
- 标识符一般为大写
- 不允许重复声明
- 值不允许修改
- 块儿级作用域
const team = ['uzi','MXLG','Ming','Letme'];
team.push('Meiko'); //不报错,常量地址没有发生变化
注意:对象属性修改和数组元素变化不会出发const错误
应用场景:声明对象类型使用const,非对象类型声明选择let
1.2 解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
//数组的解构赋值,按顺序取值
const arr = ['张学友', '刘德华', '黎明', '郭富城'];
let [zhang, liu, li, guo] = arr;
//对象的解构赋值,按key取值
const lin = {name: '林志颖',tags: ['车手', '歌手', '小旋风', '演员']};
let {name, tags} = lin;
//复杂解构
let wangfei = {name: '王菲',age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [{name: '窦唯'},{name: '李亚鹏'},{name: '谢霆锋'}]
};
let {songs: [one, two, three], history: [first, second, third]} = wangfei;
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
1.3 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用
${xxx}
形式输出变量
// 定义字符串
let str =
`<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
// 变量拼接
let star = '王宁';
let result = `${star}在前几年离开了开心麻花`;
注意:当遇到字符串与变量拼接的情况使用模板字符串
1.4 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = "Liwker";
function hello(){
console.log("Hello~");
}
const obj = {
// 简化版
name,
hello,
// 常规定义方法
hi: function(){
console.log("Hi~");
},
// 简化定义方法
say(){
console.log(this.name);
}
}
obj.hello();
obj.say();
1.5 箭头函数
ES6允许使用箭头(=>)定义函数
箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
- 箭头函数this是静态的,指向声明时所在作用域下this 的值,就连call()都不能改变
- 箭头函数不能作为构造函数实例化
- 不能使用arguments
1.通用写法:
let fn = (a, b, c) => {
return a+b+c;
};
2.省略版(小括号和花括弧):
let fn2 = a => a+a; // 自加
注意:箭头函数不会更改this指向,用来指定回调函数会非常合适。
//需求-1 点击 div 2s 后颜色变成『粉色』
ad.addEventListener("click", function(){
//定时器
setTimeout(() => {
//修改背景颜色 this
this.style.background = 'pink';
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
// 常规方法
// const result = arr.filter(function(item){
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// });
// 箭头函数
const result = arr.filter(item => item % 2 === 0);
console.log(result);
注意:
- 箭头函数适合与 this 无关的回调:定时器, 数组的方法回调
- 箭头函数不适合与 this 有关的回调:事件回调, 对象的方法
1.6 函数形参默认值
ES6允许给函数参数赋值初始值
-
可以给形参赋初始值,一般位置要靠后
-
与解构赋值结合
function A({host='127.0.0.1',username,password,port}){ console.log(host+username+password+port);}A({ username:'Liwker', password:'123456', port:3306});
1.7 rest参数
ES6引入rest参数,用于获取函数的实参,用来代替arguments
位置是在函数声明的形参列表里
function fun(...args){}
函数的属性 arguments 是实参列表,是一个伪数组,本质是一个对象
而rest参数是一个真数组,可以调用高级函数方法
// rest 参数必须是最后一个形参function fun(a, b, ...args){ console.log(a); console.log(b); console.log(args); //[3,4,5]}fun(1,2,3,4,5)
1.8 spread扩展运算符
扩展运算符是能将数组转换为逗号分隔的参数序列,可以理解为 展开
和rest参数类似,但位置不同,扩展运算符是在 函数调用的实参列表里
fun(...test);
const test=['AA','BB','CC']function fun(){ console.log(arguments);}fun(...test); //0:'AA' 1:'BB' 2:'CC'
应用:
-
数组、对象的合并
const A = ["a", "b"];const B = ["c", "d"];const C = [...A, ...B]; // 相当于 ["a","b", "c","d"]console.log(C) //[aa,bb,cc,dd]const O1 = {a:1, b:2};const O2 = {c:3};const O3 = {...O1, ...O2};console.log(O3) //{a: 1, b: 2, c: 3}
-
数组的克隆
const A = ['a','b','c'];const B = [...A]; // 相当于 ["a","b","c"]console.log(B) //[a,b,c]
注意:如果A里有引用类型,如对象,数组,那么B里也是浅拷贝的
-
将伪数组转换为真正的数组
const A = documents.querySelectorAll('div');const B = [...A];console.log(B) // [div,div,div]// 同样对 arguments 这样的伪数组也能转换
1.9 Symbol
ES6引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点:
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象属性不能使用for…in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
-
创建
let s = Symbol('aa');let s2= Symbol('aa');console.log(s===s2) // false// Symbol.for()方法创建let s3 = Symbol.for('bb');let s4 = Symbol.for('bb');comsole.log(s3===s4) // true
-
不能与其他数据进行运算
s + 100 //errors > 100 //errors + s //error`your symbol is ${s}` // TypeError: can't convert symbol to string
Symbol内置值
除了定义自己使用的Symbol 值以外,ES6 还提供了11个内置的Symbol值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
详细请查看 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol
推荐阅读 https://es6.ruanyifeng.com/#docs/symbol
1.10 迭代器
迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作。
ES6创造了一种新的遍历命令for...of循环
原理:
- 创建一个指针对象,指向数据结构的起始位置
- 第一次调用next()方法,指针自动指向数据结构第一个成员
- 接下来不断调用next(),指针一直往后移动,直到指向最后一个成员
- 每调用next()返回一个包含value和done属性的对象
const xiyou=['AA','BB','CC','DD'];// for(let v of xiyou){// console.log(v) // 'AA','BB','CC','DD'// for in保存的是键名,for of保存的是键值// }let iterator = xiyou[Symbol.iterator]();console.log(iterator.next()); //{{value:'唐僧',done:false}}console.log(iterator.next()); //{{value:'孙悟空',done:false}}
给对象自定义
const banji = { name : "自定义", stus: [ 'aa', 'bb', 'cc', 'dd' ], // 添加迭代接口,for of本质就是调用Symbol.iterator()方法 [Symbol.iterator](){ let index = 0; let _this = this; return { next: () => { if(index < this.stus.length){ const result = {value: _this.stus[index],done: false}; //下标自增 index++; //返回结果 return result; }else { return {value: underfined,done:true}; } } } }}for(let v of banji){ console.log(v); // aa bb cc dd}
1.11 生成器
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
function * gen (){ //函数名和function中间有一个 * // 这里是第一段 yield '耳朵'; //yield是函数代码的分隔符 // 这里是第二段 yield '尾巴'; // 这里是第三段 yield '真奇怪'; // 这里是第四段}let iterator = gen(); // 执行接收返回对象console.log(iteretor.next()); // {value:'耳朵',done:false}// next()执行第一段,并且返回yield后面的值console.log(iteretor.next()); // {value:'尾巴',done:false}console.log(iteretor.next()); // {value:'真奇怪',done:false}console.log(iteretor.next()); // {value:'undefinde',done:true}
代码说明:
- * 的位置没有限制,必须在function 和 函数名中间
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的next()方法可以得到yield语句后的值
- yield相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次next方法,执行一段代码
- next方法可以传递实参,作为yield语句的返回值
实例1:生成器函数的参数传递
function * gen(args){ console.log(args); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three);}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:用生成器函数的方式解决回调地狱问题
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();
实例3:模拟异步获取数据
function one(){ setTimeout(()=>{ let data='用户数据'; iterator.next(data) },1000)}function two(){ setTimeout(()=>{ let data='订单数据'; iterator.next(data) },2000)}function three(){ setTimeout(()=>{ let data='商品数据'; iterator.next(data) },3000)}function * gen(){ let users=yield one(); console.log(users) let orders=yield two(); console.log(orders) let goods=yield three(); console.log(goods)}let iterator = gen();iterator.next();
1.12 Promise
Promise是ES6引入的异步编程的新解决方案。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
1.基本特征
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)})
2.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()函数的返回值状态也是rejectedlet result = p.then(value => { console.log(value) // return 123; // return new Promise((resolve, reject) => { // resolve('ok') // }) throw 123},reason => { console.log(reason)})console.log(result);
3.Promise.catch()方法
//catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数const p = new Promise((resolve, reject) => { setTimeout(()=>{ reject('出错啦') },1000)})p.catch(reason => { console.log(reason)})
应用:发送AJAX请求
//ajax请求返回一个promisefunction sendAjax(url){ return new Promise((resolve, reject) => { //创建对象 const x =new XMLHttpRequest(); //初始化 x.open('GET',url); //发送 x.send(); //时间绑定 x.onreadystatechange = ()=>{ if(x.readyState === 4 ){ if(x.status >= 200 && x.status < 300){ //成功 resolve(x.response) }else { //失败 reject(x.status) } } } })}//测试sendAjax("https://api.apiopen.top/getJoke").then(value => { console.log(value)},reason => { console.log(reason)})
1.13 集合
1.13.1 Set
ES6提供了新的数据结构set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用「扩展运算符』和「 for…of…』进行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add() 增加一个新元素,返回当前集合
- delete() 删除元素,返回boolean值has检测集合中是否包含某个元素,返回boolean值
- has() 检测Map中是否包含某个元素,返回boolean值
- clear() 清空集合,返回undefined
特性
let s = new Set();let s2 = new Set(['A','B','C','D'])//元素个数console.log(s2.size);//添加新的元素s2.add('E');//删除元素s2.delete('A')//检测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);//2.交集let arr2=[4,5,6,5,6]let result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item))console.log(result2);//3.并集let result3=[new Set([...arr,...arr2])]console.log(result3);//4.差集let result4= [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))console.log(result4);
1.13.2 Map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和「for…of…』进行遍历。Map的属性和方法:
- size 返回Map的元素个数
- set() 增加一个新元素,返回当前Map
- get() 返回键名对象的键值
- has() 检测Map中是否包含某个元素,返回boolean值
- clear() 清空集合,返回undefined
let m = new Map();m.set('name','ran');m.set('change',()=>{ console.log('改变!')})let key={ school:'atguigu'}m.set(key,['成都','西安']);//sizeconsole.log(m.size);//删除m.delete('name');//获取console.log(m.get('change'));// //清空// m.clear()//遍历for(let v of m){ console.log(v);}
1.14 Class
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
class shouji { constructor(brand,price) { this.brand=brand; this.price=price } call(){ console.log('我可以打电话') }}let A = new shouji('1+',1999);console.log(A)
静态成员
class Person{ static name='手机'}let nokia = new Person();console.log(nokia.name);
es5 构造函数继承
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;SmartPhone.prototype.constructor=SmartPhone;//声明子类方法SmartPhone.prototype.photo = function (){ console.log('我可以玩游戏');}const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch')console.log(chuizi);
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); this.color=color; this.size=size; } photo(){ console.log('拍照'); } playGame(){ console.log('打游戏'); } // 重写父类函数 call(){ console.log('我不仅可以打电话,还可以AI通话'); }}const xiaomi=new SmartPhone('小米',1999,'黑色','4.7inch')xiaomi.call();xiaomi.photo();xiaomi.playGame();
get和set设置
class Phone{ get price(){ console.log("价格被读取了") return 'I LOVE YOU' } set price(val){ console.log('价格被修改了') return val; }}//实例化对象let s = new Phone();s.price=12 // console.log(s.price) //其实是调用price方法
1.15 数值扩展
// Number.EPSILON是 JavaScript的最小精度,属性的值接近于 2.22044...E-16function equal(a,b){ if(Math.abs(a-b) < Number.EPSILON){ return true; }else { return false; }}console.log(equal(0.1 + 0.2 === 0.3)) //falseconsole.log(equal(0.1+0.2,0.3)) //true//二进制和八进制let b = 0b1010; //2进制let o = 0o777; //8进制let d = 100; //10进制let x = 0xff; //16进制console.log(x) //255//检测一个数是否为有限数console.log(Number.isFinite(100)); //trueconsole.log(Number.isFinite(100/0)); //falseconsole.log(Number.isFinite(Infinity)); //false//检测一个数值是否为NaNconsole.log(Number.isNaN(123)) //false//字符串转整数console.log(Number.parseInt('5213123love')); //5213123console.log(Number.parseFloat('5.123123神器')); //5.123123//判断是否为整数console.log(Number.isInteger(5)); //trueconsole.log(Number.isInteger(2.5)); //false//将小数部分抹除console.log(Math.trunc(3.45345345345)) //3//检测一个数到底是正数、负数、还是0console.log(Math.sign(100)) //1console.log(Math.sign(0)) //0console.log(Math.sign(-123)) //-1
1.16 对象方法扩展
ES6新增了一些Object对象的方法:
- Object.is() 比较两个值是否严格相等,与『===』行为基本一致(+0与NaN)
- Object.assign() 对象的合并,将源对象的所有可枚举属性,复制到目标对象
- _proto_、setPrototypeOf、setPrototypeOf可以直接设置对象的原型
//1.Object.is 判断两个值是否完全相等console.log(Object.is(120,120)) //trueconsole.log(Object.is(NaN,NaN)) //false//2.Object.assign 对象的合并const a = { name:'ran', age:12}const b = { pass:'i love you'}console.log(Object.assign(a,b)) //{name:'ran',age:'12',pass:'i love you'}//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeofconst school = { name:'尚硅谷'}const cities = { xiaoqu:['北京','上海']}Object.setPrototypeOf(school,cities)console.log(Object.getPrototypeOf(school)) //{xiaoqu: Array(2)}console.log(school) //{name: "尚硅谷"}
1.17 模块化
1.17.1 基本介绍
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
模块化规范产品,ES6之前的模块化规范有:
- CommonJS ====> NodeJS、Browserify
- AMD ====> requireJS
- CMD ====> seaJS
语法
模块功能主要有两个命令构成:export和import
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能
export let school = '尚硅谷'export function teach(){ console.log('教技能')}
import * as m1 from "./src/js/m1.js";console.log(m1);
1.17.2 暴露语法汇总
1.统一暴露
//统一暴露let school = '尚硅谷';function findjob(){ console.log('找工作吧');}//export {school,findjob}
2.默认暴露
//默认暴露export default { school:'ATGUIGU', change:function(){ console.log('我们可以改变你') }}
1.17.3 引入语法汇总
1.通用导入方式
import * as m1 from "./src/js/m1.js"import * as m2 from "./src/js/m2.js"import * as m3 from "./src/js/m3.js"
2.解构赋值方式
import {school,teach} from "./src/js/m1.js"
import {school as guigu,findJob} from "./src/js/m2.js"
import {default as m3 } from "./src/js/m3.js"
3.简便形式(只针对默认暴露)
import m3 from "./src/js/m3.js"
1.17.4 模块化方式2
<script src="./src//js/app.js" type=modeule></script>
2.ES7
- Array.prototype.includes:用来检测数组中是否包含某个元素,返回布尔类型值
- 在ES7中引入指数操作符**,用来实现幂运算,功能与Math.pow结果相同
//includes
const mingzhu = ['西游记','红楼梦','水浒传','三国演义']
console.log(mingzhu.includes('西游记')) //true
console.log(mingzhu.includes('聊斋志异')) //false
//**
console.log(2**10) // 1024
3. ES8
3.1 async函数
async和await两种语法结合可以让异步代码像同步代码一样
async函数:
- async函数的返回值为promise对象
- async返回的promise对象的结果值由async函数执行的返回值决定
async function fn(){ //1.如果返回的是一个非Promise的对象,则fn()返回的结果就是成功状态的Promise对象,值为返回值 //2.如果返回的是一个Promise对象,则fn()返回的结果与内部Promise对象的结果一致 //3.如果返回的是抛出错误,则fn()返回的就是失败状态的Promise对象 return new Promise((resolve,reject)=>{ resolve('成功的数据'); });}const result = fn();result.then(value=>{ console.log(value) //成功的数据},reason=>{ console.log(reason)})
3.2 await表达式
- await必须放在async函数中
- await右侧的表达式一般为promise对象
- await可以返回的是右侧promise成功的值
- await右侧的promise如果失败了,就会抛出异常,需要通过try…catch捕获处理
//创建Promise对象const p = new Promise((resolve, reject) => { // resolve("成功的值") reject("失败了")})//await 必须放在async函数中async function main() { try { let res = await p; console.log(res); } catch (e) { console.log(e); }}//调用函数main() //失败了
应用:发送AJAX请求
//ajax请求返回一个promisefunction sendAjax(url){ return new Promise((resolve, reject) => { //创建对象 const x =new XMLHttpRequest(); //初始化 x.open('GET',url); //发送 x.send(); //时间绑定 x.onreadystatechange = ()=>{ if(x.readyState === 4 ){ if(x.status >= 200 && x.status < 300){ //成功 resolve(x.response) }else { //失败 reject(x.status) } } } })}//async 与 await 测试async function main(){ let result = await sendAjax("https://api.apiopen.top/getJoke") console.log(result);}main();
3.3 ES8对象方法扩展
const school = { name:'尚硅谷', cities:['北京','上海','深圳'], xueke:['前端','Java','大数据','运维']};//获取对象所有的键console.log(Object.keys(school));//获取对象所有的值console.log(Object.values(school));//entries,用来创建mapconsole.log(Object.entries(school));console.log(new Map(Object.entries(school)))//对象属性的描述对象console.log(Object.getOwnPropertyDescriptor(school))const obj = Object.create(null,{ name:{ value:'尚硅谷', //属性特性 writable:true, configurable:true, enumerable:true, }})
4. ES9
4.1 运算扩展符与rest参数
function connect({host,port,...user}){ console.log(host); console.log(port); console.log(user)}connect({ host:'127.0.0.1', port:3306, username:'root', password:'root', type:'master'}) //127.0.0.1 3306 {username: "root", password: "root", type: "master"}
const AA={ username:'ran'}const BB={ password:'lyyrhf'}const CC={ job:'Java'}const D={...AA,...BB,...CC};console.log(D) //{username: "ran", password: "lyyrhf", job: "Java"}
5. ES10
5.1 对象扩展方法
//二维数组const res = Object.fromEntries([ ['name','冉海锋'], ['cities','成都','武汉']])console.log(res) //{name: "冉海锋", cities: "成都"}//Mapconst m = new Map();m.set('name','ranhaifeng')const result = Object.fromEntries(m)console.log(result); //{name: "ranhaifeng"}
5.2 字符串扩展方法
//trimlet str= ' asd 'console.log(str) //asdconsole.log(str.trimStart()) //asd 清空头空格console.log(str.trimEnd()) // asd 清空尾空格
5.3 flat与flatMap
const arr = [1,2,3,[4,5,6,[7,8,9]]]//参数为深度,是一个数字console.log(arr.flat(2)) //[1,2,3,4,5,6,7,8,9]const arr2=[1,2,3,4]const result = arr2.flatmap(item => [item * 10]);//如果map的结果是一个多维数组可以进行flat 是两个操作的结合
5.4 Symbol的description
用来获取Symbol的字符串描述
let s = Symbol('尚硅谷');console.log(s.description) //尚硅谷
5.5 私有属性
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('Liwker', 18, '45kg');console.log(girl.#age) //error console.log(girl); //Person{name: "Liwker", #age: 18, #weight: "45kg"}girl.intro(); //Liwker 18 45kg
5.6 Promise
//声明两个promise对象const p1 = new Promise((resolve, reject) => { setTimeout(()=>{ resolve('商品数据-1') },1000)})const p2 = new Promise((resolve, reject) => { setTimeout(()=>{ reject('出错了!') },1000)})//调用allsettled方法:返回的结果始终是一个成功的,并且异步任务的结果和状态都存在const res = Promise.allSettled([p1,p2]);console.log(res)// Promise {<pending>}// __proto__: Promise// [[PromiseState]]: "fulfilled"// [[PromiseResult]]: Array(2)//调用all方法:返回的结果是按照p1、p2的状态来的,如果都成功,则成功,如果一个失败,则失败,失败的结果是失败的Promise的结果const result = Promise.all([p1,p2])console.log(result)
5.7 可选链操作符
//相当于一个判断符,如果前面的有,就进入下一层级function main(config){ const dbHost = config?.db?.host console.log(dbHost) //192.168.1.100}main({ db:{ host:'192.168.1.100', username:'root' }, cache:{ host:'192.168.1.200', username:'admin' }})
5.8 动态import
btn.onclick = function(){ //使用之前并未引入,动态引入,返回的其实是一个Promise对象 import('./hello.js').then(module=>{ module.hello(); })}
5.9 BigInt类型
//大整型let n = 521n;console.log(n,typeof(n)) // 521n n //函数let n = 123;console.log(BigInt(n)) // 123n //不要使用浮点型,只能用int//大数值运算let max = Number.MAX_SAFE_INTEGER; // 9007199254740991console.log(max +1) // 9007199254740992console.log(max +2) // 9007199254740992 出问题了// 大整数不能直接与整数运算,要先转换console.log(BigInt(max)+BigInt(1)) 9007199254740992nconsole.log(BigInt(max)+BigInt(2)) 9007199254740993n
5.10 绝对全局对象globalThis
console.log(globalThis) // 相当于window,在node中为global//适用于复杂环境下直接操作window