文章目录
什么是ES?
我们经常说到的ES5、ES6到底指的是什么?
- ES是指ECMAScript,它是脚本语言的规范。而平时我们经常编写的JavaSript,是ECMAScript的一种实现,所以ES新特性其实指的就是JavaScript的新特性。我们所学的JS基础应该都是基于ES5(早在2009年12月份ECMA公司就发布了ECMAScript5),而我们嘴边所说的ES6是在2015年发布的,之后每年ECMA都会更新迭代新版本的ES,不过之后的每一版改动的内容不多。
- 我们会发现,现在关于前端的招聘信息中,要求能够熟练掌握ES6语法的技能已经是最为普遍的要求。我认为从ES5到ES6的版本迭代,是非常有意义的。我们会发现ES6在前端工程化过程中起到了很重要的推动作用。
- 关于前端发展的历史,这里就不过多介绍,如果感兴趣的话,可以自己去搜索,网上有很详细的讲解。下面的简单介绍中,我尽量用代码举例。
- 注意:为了节省时间,下面的代码实例中变量命名未遵循代码规范,请各位小朋友不要模仿,平时一定要注意命名规范!!!
ES6 新特性
1. let声明变量
let a;
let b,c,d;
let e=100;
let f=521,g='aaa',h=[];
1.1 变量不能重复声明
let star='周杰伦';
let star='林俊杰';
// Identifier 'star' has already been declared
1.2 块级作用域(主要指的是全局作用域、函数作用域、eval)
let star='林俊杰';
{
let star='周杰伦';
console.log(star);
}
console.log(star)
// 周杰伦
// 林俊杰
1.3 不存在变量提升
var people;
console.log(people);
let people="aaa";
//Identifier 'people' has already been declared
// 如果是var 这里会是undefined
1.4 不影响作用域链
{
let song='青花瓷';
fn=()=>{
console.log(song);
}
fn();
//青花瓷
}
2. const 声明常量
const star='周杰伦';
注意:
- 一定要赋初始值,不然会报错
- 一般常量是用大写
- 常量的值不能改变
- 遵顼块级作用域
- 对于数组和对象的元素修改,不算做对常量的修改,这里不会报错
3. 解构赋值
ES6中允许按照一定的模式从数组和对象中提取值,对变量进行赋值,被称为解构赋值。
3.1 数组的解构
const sdtw=['刘德华','郭富城','张学友','黎明'];
let [first,second,thrid,forth]=sdtw;
console.log(first,second,thrid,forth);
//刘德华,郭富城,张学友,黎明
3.2对象的解构赋值
const zhao={
name:'赵本山',
age:'不详',
xiaopin:()=>{
console.log('演小品');
}
};
let {name,age,xiaopin}=zhao;
console.log(name,age);
xiaopin();
//赵本山 不详
//演小品
4. 模板字符串
ES6中引入新的声明字符串的方式 => ``
4.1 声明
let str=`我也是一个字符串哦`;
console.log(str,typeof(str));
//我也是一个字符串哦 string
4.2 内容中可以直接出现换行符
let str=`<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
4.3 变量拼接
let star='沈腾';
let out =`${lovest}是一个喜剧演员`;
console.log(out);
//沈腾是一个喜剧演员
5.简化对象写法
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,更加简洁
let name='aaa';
let change=()=>{
console.log('你猜我是谁');
}
const school={
name,change,
improve(){
console.log('xxxx');
}
}
6.箭头函数
6.1 声明
let fn=function(a,b){
return a+b;
}
let fn1=(a,b)=>{
return a+b;
}
console.log(fn(1,2));
console.log(fn1(1,2));
//3
//3
6.2 关于this
this是静态的,箭头函数的this始终指向函数声明时所在作用域下的this值,也就是没有自己的this,指向外层的this。
window.name='学习ES6';
function getName(){
console.log(this.name);
}
let getName2=()=>{
console.log(this.name)
}
const school={
name:'学习很快乐'
}
getName();
//学习ES6
getName2();
//学习ES6
// call方法调用,证明箭头函数没有自己的this
getName.call(school);
//学习很快乐
getName2.call(school);
//学习ES6
6.3不能作为构造函数实例化对象
//ES5中声明构造函数并实例化对象
let Person=function (name,age){
this.name=name;
this.age=age;
};
let person=new Person('xiaoming',20);
console.log(person);
//Person {name: "xiaoming", age: 20}
let Person=(name,age)=>{
this.name=name;
this.age=age;
}
let person=new Person('xiaoming',20);
//Person is not a constructor
6.4不能使用arguments(函数内部特殊的实参)变量
let fn=function(){
console.log(arguments)
}
fn(1,2,3);
let fn=()=>{
console.log(arguments)
}
fn(1,2,3);
//arguments is not defined
6.5 箭头函数的简写
//1)省略小括号,当形参有且只有一个的时候
let add=n=>{
return n+n;
}
console.log(add(9));
//18
// 2)省略花括号,当代码体只有一句语句的时候,此时return必须省略
let pow=n=>n*n;
console.log(pow(8));
//64
7.参数默认值
ES6允许给函数参数赋值初始值
7.1 形参初始值
具有默认值的参数,一般位置要靠后(潜规则)
function add(a,b,c=10){
return a+b+c;
}
let result=add(1,2); //如果不传c结果为NaN
console.log(result);
//13
7.2 与解构赋值结合
function connect({host,username,password,port}){
console.log(host,username,password,port);
//localhost root root 3306
}
connect({
host:'localhost',
username:'root',
password:'root',
port:3306
})
8. rest参数
ES6中引入rest参数,用于获取函数的实参,用来代替arguments
// ES5 获取实参的方式
function date(){
console.log(arguments)
}
date('白芷','阿娇','思慧');
// rest参数((...)扩展运算符在下一个知识点)
function date(...args){
console.log(args);
}
date('白芷','阿娇','思慧');
//["白芷", "阿娇", "思慧"]
// rest 参数必须要放到参数最后
function date(a,b,...args){
console.log(a,b,args);
}
date(1,2,3,4,5);
//1 2 [3, 4, 5]
9. 扩展运算符
[…]扩展运算符能将【数组】转化为逗号分隔的【参数序列】
9.1 基本使用
const tfboys=['易烊千玺','王源','王俊凯'];
const tfboys=['易烊千玺','王源','王俊凯'];
// 声明一个函数,使用arguments参数
function chunwan(){
console.log(arguments);
}
chunwan(tfboys);
chunwan(...tfboys); //=>chunwan('易烊千玺','王源','王俊凯');
9.2 数组的合并
const kuaizi=['王太利','肖央'];
const fenghuang=['曾毅','玲花'];
const zuixuanxiaopingguo=kuaizi.concat(fenghuang);
console.log(zuixuanxiaopingguo);
//["王太利", "肖央", "曾毅", "玲花"]
const zuixuanxiaopingguo=[...kuaizi,...fenghuang];
console.log(zuixuanxiaopingguo);
//["王太利", "肖央", "曾毅", "玲花"]
9.3 数组的克隆
const sanzhihua=['E','G','M'];
const sanyecao=[...sanzhihua];
console.log(sanzhihua);
//["E", "G", "M"]
9.4 将伪数组转化为真正的数组
<div></div>
<div></div>
<div></div>
<script>
const divs=document.querySelectorAll('div');
const divArr=[...divs];
console.log(divArr);
//[div, div, div]
</script>
10. Symbol
ES6引入了一种新的原始数据类型Symbol,用来表示独一无二的值。它是JavaScript语言的第七种语言类型,是一种类似于字符串的数据类型
Symbol的特点:
- 1)Symbol值是唯一的,用来解决命名冲突的问题
- 2)Symbol值不能与其他数据类型进行运算
- 3)Symbol定义的对象属性不能使用for…in循环遍历获取对象键名,但是可以使用Reflect.ownKeys来获取对象的所有键名
10.1 创建基本Symbol
let s=Symbol();
console.log(s,typeof(s));
//Symbol() "symbol"
10.Symbol.html:22 false
let s2=Symbol('爱学习');
let s3=Symbol('爱学习');
console.log(s2===s3);
//false
10.2 Symbol.for创建
let s4=Symbol.for('爱学习');
let s5=Symbol.for('爱学习');
console.log(s4,s5,typeof(s4),typeof(s5));
//Symbol(爱学习) Symbol(爱学习) "symbol" "symbol"
10.3 不能与其它数据进行运算
//let result=s+100;
//let result=s>100;
let result=s+s;
//Cannot convert a Symbol value to a number
10.4 Symbol创建对象属性
let game={
contene:'text'
}
//声明一个对象
let methods={
up:Symbol(),
down:Symbol()
};
game[methods.up]=function(){
console.log('我可以改变形状');
}
game[methods.down]=function(){
console.log('我可以快速下降');
}
console.log(game);
let youxi={
name:'狼人杀',
[Symbol('say')]:function(){
console.log('我可以发言')
},
[Symbol('zibao')]:function(){
console.log('我可以自报');
}
}
console.log(youxi);
10.5 Symbol内置属性
//扩展对象功能
class Person{
static [Symbol.hasInstance](param){
console.log(param); //传递的o
//{}
console.log('我被用来检测类型了');
//我被用来检测类型了
}
}
let o={};
console.log(o instanceof Person) //判断是否是该构造函数的实例化对象
// false
//阻止数组合并
const arr=[1,2,3];
const arr2=[4,5,6];
arr2[Symbol.isConcatSpreadable]=false;
console.log(arr.concat(arr2));
11. 迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作。
迭代器的工作原理:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next()方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next()方法,指针一直往后移动,直到指向最后一个成员
- 每调用next()方法返回一个包含value和done属性的对象
11.1 简单的迭代器之for…of…
const xiyou=['唐僧','孙悟空','猪八戒','沙僧'];
for(let v of xiyou){
console.log(v);
}
//唐僧
//孙悟空
//猪八戒
//沙僧
11.2 迭代器自定义遍历对象
//声明一个对象
const banji={
name:'终极一班',
stus:[
'小明',
'小天',
'小宁',
'小花'
],
[Symbol.iterator](){
//索引变量
let index=0;
return {
//重写迭代器中的next()函数
next:()=>{
if(index<this.stus.length){
const result= {value:this.stus[index],done:false};
index++;
return result;
}else{
return {value:undefined,done:true};
}
}
}
}
}
for(let v of banji){
console.log(v)
}
//小明
//小天
//小宁
//小花
12. 生成器函数
生成器其实就是一个特殊的函数,函数名前加’ * ’
function * gen(){
console.log(111);
console.log(222);
console.log(333);
console.log(444);
}
let iterator=gen(); //=>迭代器对象
console.log(iterator)
iterator.next();
iterator.next();
iterator.next();
iterator.next();
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
yield '真奇怪';
}
for(let v of gen()){
console.log(v)
}
//一只没有耳朵
//一只没有尾巴
//真奇怪
12.1 生成器函数参数
function * gen(arg){
console.log(arg);
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());
// next方法可以传入实参,这个参数将作为上一个yield的返回结果
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
12.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();
//实现每隔1、2、3秒输出
//111
//222
//333
// 模拟获取(利用计时器函数代替真实获取数据的ajax的请求) 用户数据 订单数据 商品数据
function getUser(){
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 getUser();
console.log(users);
let orders=yield getOrders();
console.log(orders);
let goods=yield getGoods();
console.log(goods);
};
let iterator=gen();
iterator.next();
13. Promise
promise实际上就是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
13.1 Promise基本语法
const p=new Promise((resolve,reject)=>{
setTimeout(() => {
let data='数据库中的用户数据';
resolve(data);
let err='数据读取失败';
reject(err);
//一个请求要么成功要么失败,所以要么返回成功结果,要么返回失败结果。成功时默认返回成功数据
}, 1000);
})
p.then(value=>{
console.log(value);
//数据库中的用户数据
},reason=>{
console.log(reason);
//数据读取失败
})
13.2 Promise-then方法
// 创建 promise对象
const p=new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('用户数据');
// reject('出错了');
}, 3000);
})
// 调用then 方法 ,then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定
const result=p.then(value=>{
console.log(value);
//用户数据
// 1.非 promise类型的属性
// 如果回调函数中返回的结果是 非promise 类型的属性,状态为成功,返回值为对象的成功值
// return 123;
// 2.是promise对象
//则遵循promise对象的方式
// return new Promise((resolve,reject)=>{
// resolve('ok');
// });
// 3.抛出错误
throw new Error('出错了');
//Error: 出错了
},reason=>{
console.error(reason);
})
console.log(result);
14. 集合(Set)
ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯一的。集合实现了Iterator接口,所以可以使用【扩展运算符】和【for…of…】进行遍历。
集合的属性和方法:
- size:返回集合的元素个数
- add:增加一个新元素,返回当前集合
- delete:删除元素,返回boolean值
- has:检测集合中是否包含某个元素,返回boolean值
let s=new Set();
let s2=new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
console.log(s2);
//Set(4) {"大事儿", "小事儿", "好事儿", "坏事儿"}
// 元素个数
console.log(s2.size)
//5
// 添加新的元素
s2.add('喜事儿');
console.log(s2);
//Set(5) {"大事儿", "小事儿", "好事儿", "坏事儿","喜事儿"}
// 删除元素
s2.delete('坏事儿');
console.log(s2);
//Set(4) {"大事儿", "小事儿", "好事儿","喜事儿"}
// 检测
console.log(s2.has('好事儿'));
//true
// 清空
s2.clear();
console.log(s2)
//Set(0) {}
for(let v of s2){
console.log(v)
}
//集合的简单应用
let arr=[1,2,3,4,5,6,5,4,3,2,1];
let arr2=[4,5,6,5,6];
//数组去重
let result=[...new Set(arr)];
console.log(result);
//(6) [1, 2, 3, 4, 5, 6]
//求两个数组的交集
let result=[...new Set(arr)].filter(item=>new Set(arr2).has(item))
console.log(result);
//(3) [4, 5, 6]
//求两个数组的并集
let union=[...new Set([...arr,...arr2])];
console.log(union);
//(6) [1, 2, 3, 4, 5, 6]
//两个数组的差集
let diff=[...new Set(arr)].filter(item=>!(new Set(arr2).has(item)));
console.log(diff);
//(3) [1, 2, 3]
15. Map
ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了Iterator接口,所以可以使用【扩展运算符】和【for…of…】去遍历。
Map的属性和方法:
- size:返回Map的元素个数
- set:增加一个新元素,返回当前Map
- get:返回键名对象的键值
- has:检测Map中是否包含某个元素,返回boolean值
- clear:清空,返回undefined
// 声明Map
let m = new Map();
// 添加元素
m.set('name','周杰伦');
m.set('change',function(){
console.log('我可以改变你');
})
let key={
school:'清华大学'
};
m.set(key,['北京','上海','深圳']);
console.log(m);
//接着上面的
console.log(m.size);
//3
// 删除
m.delete('name');
console.log(m)
//Map(2) {"change" => ƒ, {…} => Array(3)}
// 获取
console.log(m.get('change'));
//ƒ (){
// console.log('我可以改变你');
// }
// 清空
m.clear();
console.log(m);
//Map(0) {}
// 遍历
for(let v of m){
console.log(v);
}
16. 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('华为',5999);
// Huawei.call();
// console.log(Huawei);
// ES6中使用class
class Phone{
// 构造方法 名字不能修改
constructor(brand,price){
this.brand=brand;
this.price=price;
}
// 方法必须使用该语法,不能使用es5的对象完整形式
call(){
console.log("我可以打电话");
}
}
let onePlus=new Phone('1+',1999);
console.log(onePlus);
//Phone {brand: "1+", price: 1999}
onePlus.call();
//我可以打电话
16.1 class的静态成员
静态属性 属于类本身,而不属于它的实例对象,利用实例对象无法调用,当可以利用类本身调用。
class Phone{
static name='手机';
phone='华为';
static change(){
console.log('我可以改变世界');
}
}
let nokia=new Phone();
console.log(Phone.name);
//手机
console.log(nokia.name);
//undefined
console.log(nokia.phone);
//华为
nokia.change();
//nokia.change is not a function
Phone.change();
//我可以改变世界
16.2 class继承
先来看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); //利用原型链实现对父类型对象的方法继承,利用call()方法并借助父类型构造函数初始化相同属性
this.color=color;
this.size=size;
}
// 设置子级构造函数的原型
smartPhone.prototype=new Phone;
smartPhone.prototype.constructor=smartPhone;
// 声明子类的方法
smartPhone.prototype.photo=function(){
console.log('我可以拍照');
}
smartPhone.prototype.playGame=function(){
console.log('我可以玩游戏');
}
const phone=new smartPhone('华为',5499,'黑色','5.5inch');
console.log(phone);
//smartPhone {brand: "华为", price: 5499, color: "黑色", size: "5.5inch"}
ES6 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('我可以打游戏');
}
call(){ //子类对父类方法的重写
console.log('我可以进行视频通话');
}
}
const phone=new smartPhone('小米',2499,'粉色','4.7inch');
console.log(phone);
//smartPhone {brand: "小米", price: 2499, color: "粉色", size: "4.7inch"}
phone.call(); //子类重写父类方法后,调用子类的重写方法,不在调用父类方法
//我可以进行视频通话
phone.photo();
//我可以拍照
phone.playGame();
//我可以打游戏
16.3 class中的get和set
class Phone {
constructor(){
this._price=null;
}
//get和set 不能和属性重名,一般以_区分
get price() {
console.log('价格属性被读取了');
// return 'iloveyou';
return this._price;
}
set price(newVal){
console.log('价格属性被修改');
this._price=newVal;
}
}
//实例化对象
let s = new Phone();
console.log(s.price);
//价格属性被读取了
//null
s.price='free';
console.log(s.price);
//价格属性被修改
//价格属性被读取了
//free
17. ES6中的数值扩展
- Number.EPSILON 是JavaScript:表示的最小精度
// EPSILON 属性的值接近于2.2204460492503130808472633361816E-16
// 用在浮点数计算上,对精度进行设置的
console.log(0.1+0.2===0.3);
//false
function equal(a,b){
if(Math.abs(a-b)<Number.EPSILON){
return true;
}else{
return false;
}
}
console.log(equal(0.1+0.2,0.3));
//true
- 二进制和八进制
let b=0b1010;
let o=0o777;
let d=100;
let x=0xff;
console.log(b);
//10
console.log(o);
//511
console.log(d);
//100
console.log(x);
//255
- Number.isFinite() 检测一个数值是否为有限数
console.log(Number.isFinite(100));
//true
console.log(Number.isFinite(100/0));
//false
console.log(Number.isFinite(Infinity)); //无穷
//false
- Number.isNaN() 检测一个数值是否为NaN
console.log(Number.isNaN(123));
//false
- Number.parseInt() 字符串转整数,Number.parseFloat() 字符串转浮点型
console.log(Number.parseInt('5211314love'));
//5211314
console.log(Number.parseFloat('3.1415926上神奇'));
//3.1415926
- Number.isInteger() 判断一个数是否为整数
console.log(Number.isInteger(5));
//true
console.log(Number.isInteger(2.5));
//false
- Math.trunc() 将数字的小数部分抹掉
console.log(Math.trunc(3.5));
//3
- Math.sign() 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
//1
console.log(Math.sign(0));
//0
console.log(Math.sign(-20000));
//-1
18. 对象方法扩展
- Object.is()判断两个值是否完全相等
console.log(Object.is(120, 120)); //===
//true
console.log(Object.is(NaN, NaN));
//true
console.log(NaN === NaN); //我们知道NaN和任何数去作比较,除了不等于,其他结果都为false
//false
- Object.assign()对象的合并 ,如果对象中有相同的属性,后边的会覆盖掉前边的,如果不重复,则都保留
const config1={
host:'localhost',
port:3306,
name:'root',
pass:'root',
test:'test'
};
const config2={
host:'https://baidu.com',
port:33060,
name:'admin',
pass:'admin',
test2:'test2'
}
console.log(Object.assign(config1,config2));
//{host: "https://baidu.com", port: 33060, name: "admin", pass: "admin", test: "test","test2"}
- Object.setPrototypeOf() 设置原型对象 Object.getPrototypeof()获取
const compony={
name:'腾讯'
}
const cities={
address:['北京','上海','深圳']
}
Object.setPrototypeOf(compony,cities); //cities作为compony的原型对象
console.log(Object.getPrototypeOf(compony));
//{address: Array(3)}=> address: (3) ["北京", "上海", "深圳"]
console.log(Object.getPrototypeOf(cities));
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(compony);
//{name: "腾讯"}
19. ES6模块化
// 模块化 : 是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来
// 模块化的好处: 1)防止命名冲突 2)代码重用 3)高维护性
// ES6之前的模块化规范有:
// CommonJS =>NodeJS,Browserify
// AMD =>requireJS
// CMD => seaJS
// ES6模块化语法
// 模块功能主要由两个命令构成 :export 和 import
// export 命令用于规定模块的对外接口
// import 命令用于输入其他模块提供的功能
// 分别暴露 ,统一暴露,默认暴露
20. 装饰器
详细介绍请点击这篇文章查看:
ES6中装饰器的简单介绍
ES7 新特性
1. includes()
该方法用来判断是否存在其中,类比indexof方法。
const mingzhu=['西游记','红楼梦','三国演义','水浒传'];
// 判断
console.log(mingzhu.includes('西游记'));
//true
console.log(mingzhu.includes('钢铁是怎么样练成的'));
//false
2. 幂运算(**)
console.log(2 ** 10); //ES7幂运算
//1024
console.log(Math.pow(2, 10));//math函数幂运算
//1024
ES8 新特性
1. async和await
两种语法结合可以让异步代码像同步代码一样
async 函数 :
- async函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值决定。
await表达式 :
- await 必须写在async函数中
- await右侧的表达式一般为promise对象
- await返回的是promise成功的值
- await的promise失败了,就会抛出异常,需要通过try…catch 捕获处理
async function fn(){
// return '好好学习';
// 如果返回的结果不是一个Promise类型的对象,返回的结果就是成功的Promise对象
// return;
// 抛出错误,返回的结果是一个失败的Promise
// throw new Error('出错了');
// 返回的结果如果是一个Promise对象
return new Promise((resolve,reject)=>{
resolve('成功的数据');
//reject('失败的值');
});
}
const result=fn();
// console.log(result);
result.then(value=>{
console.log(value);
//成功的数据
},reason=>{
console.log(reason);
//失败的数据
})
const p= new Promise((resolve,reject)=>{
resolve("用户数据");
})
// await 要放到async函数中
async function main(){
try{
let result= await p;
console.log(result);
//用户数据
}
catch(e){
console.log(e);
}
}
main();
2. 新增对象方法
// 声明对象
const compony={
name:'阿里',
cities:['北京','上海','深圳'],
gangwei:['前端','Java','大数据','运维']
};
// 获取对象所有的键
console.log(Object.keys(compony));
// 获取对象所有的值
console.log(Object.values(compony));
// entries
console.log(Object.entries(compony)); // =>返回的是一个数组,而每个成员又是一个数组。 方便创建一个map
console.log(Object.getOwnPropertyDescriptors(compony)); //创建对象时属性描述对象的一种形式
const obj=Object.create(null,{
name:{
//设置值
value:'好好学习',
//属性特性
writable:true,
configurable:true,
enumerable:true
}
})
ES9 新增特性
1. ES9中的对象展开
// Rest 参数与spread扩展运算符在ES6中已经引入,不过ES6中只针对于数组,在ES9中为对象提供了像数组一样的 rest参数和扩展运算符
function connect({host,port,...user}){
console.log(host);
//127.0.0.1
console.log(port);
//3306
console.log(user);
//{username: "root", password: "root", type: "master"
}
connect({
host:'127.0.0.1',
port:3306,
username:'root',
password:'root',
type:'master'
});