es6学习笔记

es6 学习笔记。

一、定义(声明)变量

**let const var **
块级作用域。let变量,const 常量(不能修改)。
es6之前:var变量

var a=12
function fn(){
alert(a);//12
}
-----------
var a=12
function fn(){
alert(a);//undefined
var a=3;
}

二、解构赋值

常用于数据交互,ajax

注意:左右俩边都要相对应。结构赋值可以给默认值。

let [a,b,c]=[10,22,33];
console.log(a,b,c);//10 22 33

let [a,b,c]=[10,[22,33]];
console.log(a,b,c);//10 [22,33] undefined

let [a,[b,c]]=[10,[22,33]];
console.log(a,b,c);//10 22 33

let [a,b,c]=[12,22];
console.log(a,b,c);//12,22,undefined

let [a,b,c='默认']=[12,22];
console.log(a,b,c);//12,22,默认

let [a,b,c=‘默认’]=[12,22,undefined];
console.log(a,b,c);//12,22,默认

let [a,b,c=‘默认’]=[12,22,null];
console.log(a,b,c);//12,22,null

三、字符串模板与新增字符串

一、字符串模板: ``反引号+${}。

之前:
let name = ‘张三’;
let age =16;
let src='我叫'+name+'今年'+age+'岁';
console.log(src);//我叫张三今年18

let name = ‘张三’;
let age =16;
let src=`我叫${name}今年${age}`;
console.log(src);//我叫张三今年18

传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。
includes,startsWith,endsWith

includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

这三个方法都支持第二个参数,表示开始搜索的位置。

let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。

新增字符串查找:includes(无法判断后缀)

str.index(要找到的东西) 返回索引(位置从第几位开始)
str.includes(要找到的东西) 返回值 truefalse

判断浏览器
if(navigator.userAgent.includes('chrome')){
  alert('chrome');
}else{
  alert('! chrome');
}

字符串以什么开头结尾
str.startsWith(检查的东西)

  •   http
    
  •   地址
    

str.endsWith(检查的东西)

  •  .png
    

重复字符串:repeat(次数)

let str='我';
alert(str.repeat(3));//我我我

填充字符串(es2016,es6即ES2015,在2015年6月提出。):

  • str.padStart( 整个字符串长度(原本的+打算加的),填充的东西); 往前填充
  • str.padEnd(整个字符串长度(原本的+打算加的),填充的东西); 往后填充
let str=‘Apple’;
let padStr=‘xxx’;
srt.padStart(str.length+padStr.length,padStr);// xxxApple

四、函数默认参数、箭头函数、剩余参数

ES5中不能直接为函数的参数指定默认值,只能通过以下的变通方式:

function show(a,b){
	a=a || '我';
	b=b || 'ai';
}

当传入的参数为0或者false时,会直接取到后面的值,而不是传入的这个参数值。
在这里插入图片描述
剩余函数rest() ...
ES6 引入 rest 参数(形式为“…变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。

作用:可以展开或者收缩函数,也可以求剩余

function fun(a, ...rest) {
  console.log(a)
  console.log(rest)
}
fun(1) // 1 []
fun(1, 2, 3, 4) //1 [2,3,4]
 
又比如,在前面定义2个参数
 
function fun(a, b, ...rest) {
  console.log(a, b)
  console.log(rest)
}
fun(1, 2) // 1 2 []
fun(1, 2, 3, 4) 1 2 [3,4]
 
注意:剩余参数后面不能跟其他参数,否则会报错
function func(a, ...rest, b) {}//报错
 
当使用剩余参数后,函数的length属性会发生一些变化
function func(a, b, ...rest) {
}
func.length // 2
即length不包含rest,为2 
 
剩余参数前面可以不跟其他参数,即一个参数也没有。如
function func(...rest) {
  console.log(rest)
}
func(1) // [1]
func(1, 2, 3, 4) // [1,2,3,4]
 也可以做展开:
 let str=[1,2,3,4];
 alert(...str);//1,2,3,4
 
 
注意:rest不能和arguments一起使用,会报错
function func(...rest) {
  console.log(rest)
  console.log(arguments)
}

restarguments的区别是什么呢?
arguments是一个伪数组(Array-like)
剩余参数是一个真正数组(Array),具有Array.prototype上的所有方法
arguments上有callee,callee上有caller

转换数组:

Array.prototype.slice.apply(arguments)

…Array
箭头函数
( )= > { 语法 }

function show(a=1{
alert(a);//1
}
show();//1

let show = (a=2)=>{
alert(a);//2
}
show();//2

注意:
1, this 定义函数所在的对象,不再是运行时所在的对象
2. 箭头函数里面没有arguments ,用 …
3. 箭头函数不能当构造函数

let show =()=>{
 this.name='abc';
}
let s =new show();
alert(s.name);//报错

var id=2;
let show =()={
id=1;
    setTimeout(()={
    alert(this.id);
  },1000)
}
show(); // 1

let str={1,2,3,4};
let show = ()=>{
  alert(arguments);
}
show(str); //报错
let str={1,2,5,4};
let show = (a)=>{
  alert(..a.sort());
}
show(str); /1,2,4,5

sort():排序

五、数组

1.forEach() —2.map()—3.filter()—5.some()—6.every() 都可以接受俩个参数,一个为循环回调函数,一个为this指向

1.forEach()

用来代替for循环:

let arr = [1,2,3,4];
arr.forEach(function(item,index,arr){
console.log(this,item,index,arr);
},555);
555 1 0 [1,2,3,4]
555 2 1 [1,2,3,4]
555 3 2 [1,2,3,4]
555 4 3 [1,2,3,4]

arr.forEach((item,index,arr){
console.log(this,item,index,arr);
},555);
改为箭头函数,this指向还是window
2.map()

map返回一个新的数组,可以改变数组的值,需要配合 return;若没有 return ,相当于 forEach

let arr = [1, 2, 3];
let newArr = arr.map((item, index, arr) => {
    return item * 2;
})
console.log(arr) // [1, 2, 3]
console.log(newArr) // [2, 4, 6]


let arr=[1,2,3,4];
let res=arr.map((item, index, arr)=>{
return Math.pow(item,2);
return item**2;
});
console.log(res);
3.filter()

filter可以过滤数组,包含满足条件的数组项,返回一个新数组
可以用于过滤不要的元素,retrun true 就留下来

let arr = [1, 2, 3];
let newArr = arr.filter((item, index, arr) => {
    return item <= 2;
})
console.log(arr) // [1, 2, 3]
console.log(newArr) // [1, 2]
4.some()

some返回布尔值,如果有一个满足条件的值则返回 true

let arr = [1, 2, 3];
let result = arr.some((item, index, arr) => {
    return item < 2;
})
console.log(result) // true
5.every()

every返回布尔值,如果所有数组项都满足条件则返回true

let arr = [1, 2, 3];
let result = arr.every((item, index, arr) => {
    return item < 2;
})
console.log(result) // false
--
let arr = [1, 2, 3];
let result = arr.every((item, index, arr) => {
    return item > 0;
})
console.log(result) // true

6.reduce()----从左往右

接受的参数 prev 上一个 cur 当前 index arr

求数组的和
let arr=[1,2,3,4,5,6,7,8,9,10];
let res=arr.reduce((prev,cur,index,arr)=>{
return prev +cur;
});
console.log(res);

求次方:2的3次方
Math.pow(2,3);
es2017 : 2**3

7.reduceRight()—从右往左

同上

8 for…of 循环

keys() 数组的下标
entries() 数组的某一项

let arr=[1,2,3,4];
for(let val of  arr){
console.log(val);//1,2,3,4
}

let arr=[1,2,3,4];
for(let index of  arr.keys()){
console.log(val);//0,1,2,3

let arr=[1,2,3,4];
for(let item of  arr.entries()){
console.log(item);//[0,1][1,2][2,3][3,4]

let arr=[1,2,3,4];
for(let [key,item] of  arr.entries()){
console.log(item);//0,1   1,2   2,3   3,4
9 Array.from()
  • Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。
  • 所谓类数组对象,最基本的要求就是具有length属性的对象。
  • 将一个类数组对象转换为一个真正的数组,必须具备以下条件:

1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。

2、该类数组对象的属性名必须为数值型或字符串型的数字

ps: 该类数组对象的属性名可以加引号,也可以不加引号

let json={
   0:'apple',
   1:'banana',
   2:'orange'     
}
let str=Array.from(json);
console.log(str); //undefined, undefined, undefined
let json={
   0:'apple',
   1:'banana',
   2:'orange' ,
   length:3    
}
let str=Array.from(json);
console.log(str); //apple,banana,orange

Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下:

let arr = [12,45,97,9797,564,134,45642]
console.log(Array.from(arr, item => item + 1)) // [ 13, 46, 98, 9798, 565, 135, 45643 ]
10Array.of()

Array.of( )方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型:

let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]); // 1
console.log(items[1]); // 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]); // 2
11 arr.find()

查找元素,第一个符合条件的,没有则undefined

let arr=[1,2,3,4];
let str=arr.find((val,index,arr)=>{
return val>2;
});
console.log(str);//3,4
12 arr.findIndex()

查找位置,第一个符合条件的,没有则返回 -1

13 arr.fill

填充

let s=new Array(6);
s.fill('wo');
console.log(s);//wo,wo,wo,wo,wo,wo 
s.fill('wo',2,4);
console.log(s);//null,null,wo,wo,wo,null

六、对象简洁语法与对象新增

  • 同名的属性可以省略不写
  • 对象中的方法中的 : function 可以省略不写
  • 方法简写,不要用箭头函数(建议)
let name ='xiao';
let age = 16;
let json={
   name,  //name:name,
   age ,  //age :age ,
   show(){
   return 3;
   }  //show:function(){return 3;};
};
console.log(json.name,json.age,json.show());//xiao,16,3

Object.is()

ES5 比较两个值是否相等,只有两个运算符:相等运算符( == ) 和严格相等运算符(===)。它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0。JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

console.log(NaN == NaN); //false
console.log(Number.isNaN(NaN) ); // true
let b = Object.is(NaN,NaN);
console.log(b);//true

Object.is(+0,-0);//false
Object.assign()
  • 用来合并对象
    语法: Object.assign(target, …sources) target: 目标对象,sources: 源对象
    用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);

console.log(target); // Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget); // Object { a: 1, b: 4, c: 5 }

  • 复制对象
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
Object.keys() 数组的下标
Object.entries() 数组的某一项
let {keys,values,entries} = Object;
let json={
   a:1,
   b:2,
   c:3
};

for(let key of keys(json)){
  console.log(key);//a,b,c
}
for(let value of values(json)){
  console.log(value);//1,2,3
}
for(let item of entries(json)){
  console.log(item );//  [a:1],[b:2],[c:3]
}
for(let [key,value] of entries(json)){
  console.log([key,value]);//  a 1, b 2,c 3
}

七、Promise

作用:解决异步回调

传统方式:大部分用回调函数,事件

ajax(url,{
//获取token
  ajax(url,()=>{
   //用token获取用户信息
     ajax(url,()=>{
     //用用户信息获取用户相关新闻

     });
  });
});

语法:new Promise( function (resolve, reject) {}).then(res=>{}).catch(err=>{});

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
   // resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

new Promise( function (resolve, reject) {}).then(res=>{}).catch(err=>{});

例子:

let a=10;
let ss = new Promise(
  function (resolve, reject) {
	 if(a==10){
	  resolve('成功')
	 }else{
	 reject('失败')
	 };
 
  }
).then(
  res => {console.log(res)},  // 成功
  err => {console.log(err)} // 失败
)

Promise.resolve('aaa') : 将现有的东西,转换为一个Promise对象,resolve 成功状态
等价于:
new Promise(resolve=>{
resolve(‘aaa’);
});

Promise.reject('bbb') : 将现有的东西,转换为一个Promise对象,reject 失败状态
等价于:
new Promise((reject,resolve)=>{
reject(‘bbb’);
});

Promise.all({p1,p2,p3}); 把 Promise 打包,放到一个数组里面,打包完还是一个promise对象;
必须确保p1,p2,p3 所有的 Promise.resolve('aaa对象,状态都是成功的,

Promise.race({p1,p2,p3}); 把 Promise 打包,放到一个数组里面,打包完还是一个promise对象;
有一个 Promise.resolve('aaa对象,就返回

let p1= Promise.resolve('aaa');
let p2= Promise.resolve('bbb');
let p3= Promise.resolve('ccc');

Promise.all({p1,p2,p3}).then(res=>{
	//console.log(res);
	let [res1,res2,res3]=res;
	console.log(res1,res2,res3);//aaa,bbb,ccc
});

例子:模仿用户登录,获取信息

let s=1; //状态码
let userlogin=(resolve,reject)=>{
	setTimeout(()=>{
		  if(s == 1){
		    resolve({data:'用户登录成功',msg:'',token:''});
		   }else{
			reject('用户登录失败');
		   };
	},1000);

};
let getUserInfo=(resolve,reject)=>{
	setTimeout(()=>{
		  if(s == 1){
		    resolve({data:'获取用户信息成功',msg:'',token:''});
		   }else{
			reject('获取用户信息失败');
		   };
	},1000);

};

new Promise(userlogin).then(res=>{
	console.log('用户登录成功');
	return new Promise(getUserInfo);
}).then(res=>{
	console.log('获取用户信息成功');
	console.log(res);
});


八、模块化

es5之前的javascript中是没有模块化概念的。如果要进行模块化操作,需要引入第三方的类库。随着技术的发展,前后端分离,前端的业务变的越来越复杂化。直至ES6带来了模块化,才让javascript第一次支持了module。ES6的模块化分为导出(export)与导入(import)两个模块。

在ES6中每一个模块即是一个文件,在文件中定义的变量,函数,对象在外部是无法获取的。如果你希望外部可以读取模块当中的内容,就必须使用export来对其进行暴露(输出)。

import 特点:
a)可以是绝对路径,也可以是相对路径
b)import 模块只会导入一次,无论你引入多少次
c)有提升效果,会自动提升到顶部
d)导出去的模块内容,如果里面有定时器更改,外面也会改动
e)不能动态引入,要动态引入得用import()

import()特点:
按需加载,可以动态引入,默认import语法不能写到if之类里面;
返回值,是一个promise 对象

错误:
<script type="module">
let a=1;
if(a == 1){
	import a from './test1.js';
}else{
   import a from './test2.js';
};
</script>

正确:
import('./modules.js').then(res=>{
console.log(res);
});

动态引入+promise
<script type="module">
	Promise。all([
	   import('./modules/1.js');
   	   import('./modules/2.js');
	]).then(([m1,m2])=>{
    console.log(m1);
    console.log(m2);
	});
</script>
test.js文件:
let myName="laowang";
let myAge=90;
let myfn=function(){
    return "我是"+myName+"!今年"+myAge+"岁了"
}
export {
    myName,
    myAge,
    myfn
}
/******************************接收的代码调整为**********************/
<script type="module">
import {myfn,myAge,myName} from "./test.js";

console.log(myfn());//我是laowang!今年90岁了
console.log(myAge);//90
console.log(myName);//laowang
</script>

如果你不想暴露模块当中的变量名字,可以通过as来进行操作:

let myName="laowang";
let myAge=90;
let myfn=function(){
    return "我是"+myName+"!今年"+myAge+"岁了"
}
export {
    myName as name,
    myAge as age,
    myfn as fn
}

/******************************接收的代码调整为**********************/
import {fn,age,name} from "./test.js";
console.log(fn());//我是laowang!今年90岁了
console.log(age);//90
console.log(name);//laowang


也可以直接导入整个模块,将上面的接收代码修改为:
import * as info from "./test.js";//通过*来批量接收,as 来指定接收的名字
console.log(info.fn());//我是laowang!今年90岁了
console.log(info.age);//90
console.log(info.name);//laowang

默认导出(default export)
一个模块只能有一个默认导出,对于默认导出,导入的名称可以和导出的名称不一致。

/******************************导出**********************/
export default function(){
    return "默认导出一个方法"
}
/******************************引入**********************/
import myFn from "./test.js";//注意这里默认导出不需要用{}
console.log(myFn());//默认导出一个方法

可以将所有需要导出的变量放入一个对象中,然后通过default export进行导出

/******************************导出**********************/
export default {
    myFn(){
        return "默认导出一个方法"
    },
    myName:"laowang"
}
/******************************引入**********************/
import myObj from "./test.js";
console.log(myObj.myFn(),myObj.myName);//默认导出一个方法 laowang


同样也支持混合导出
/******************************导出**********************/
export default function(){
    return "默认导出一个方法"
}
export var myName="laowang";
/******************************引入**********************/
import myFn,{myName} from "./test.js";
console.log(myFn(),myName);//默认导出一个方法 laowang

重命名export和import
如果导入的多个文件中,变量名字相同,即会产生命名冲突的问题,为了解决该问题,ES6为提供了重命名的方法,当你在导入名称时可以这样做:

/******************************test1.js**********************/
export let myName="我来自test1.js";
/******************************test2.js**********************/
export let myName="我来自test2.js";
/******************************index.js**********************/
import {myName as name1} from "./test1.js";
import {myName as name2} from "./test2.js";
console.log(name1);//我来自test1.js
console.log(name2);//我来自test1.js

九、class类

类:constructor构造方法

es5中:
在这里插入图片描述
es6中:
在这里插入图片描述
第一、首先要明白,ES6的class只是一个语法糖,class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已,其实还是使用ES5的构造函数来实现的。
可以看到类里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5的构造函数Point,对应ES6的Point类的构造方法;ES5的构造函数原型prototype上的方法对应ES6的 class类里面写的函数,即ES6的各种现象都可以使用ES5进行解释。

ES6的类中的定义方法的时候,前面不需要加function关键字,另外方法直接不能加逗号分隔,加了会报错;
类里面是写语句的,所以不能写逗号,但可以写分号的,因为里面的一个方法就是一个语句;

类的静态方法 static
只能用类来调用:

class Pro{
	constructor(){
	}
	showNmae(){
	return '这是showNmae方法';
	}
	static aaa(){
	return '这是静态方法';
	}
}
let p1=new Pro();
console.log(p1.showNmae);
console.log(Pro.aaa());

继承 extends
类名:首字母大写,
super()

//父类
class Prson{
 constructor(name){
	 this.name = name;
	}
	showName(){
	console.log('父类');
	return `这是showName方法,名字为:${this.name}`;
	}
}
//子类
class Student extends Prson{
    constructor(name,skill){  //arg 接受的参数
		super(arg); 
		this.skill=skill;
	}
	showSkill(){
 		return '我的技能${skill}'
	}
	showName(){
	super.showName();  //父类的方法执行
	
	console.log('子类');
	return `这是showName方法,名字为:${this.name}`;
	}
}

let str1 = new Student('ling','上学');
console.log(str1.showName());//这是showName方法,名字为:ling
console.log(str1.showSkill());//我的技能上学

十、symbol与generator函数

Symbol是由ES6规范引入的一项新特性,它的功能类似于一种标识唯一性的ID。
每个Symbol实例都是唯一的。因此,当你比较两个Symbol实例的时候,将总会返回false:

let s1 = Symbol();
let s2 = Symbol('another symbol');
typeof s1  // 'symbol'

let s1 = Symbol()
let s2 = Symbol('another symbol')
let s3 = Symbol('another symbol')
s1 === s2 // false
s2 === s3 // false

Symbol类型的key是不能通过Object.keys()或者for…in来枚举的,它未被包含在对象自身的属性名集合(property names)之中。所以,利用该特性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义

let obj = {
   [Symbol('name')]: 'aaa',
   age: 18,
   title: 'Engineer'
}

Object.keys(obj)   // ['age', 'title']

for (let p in obj) {
   console.log(p)   // 分别会输出:'age'  'title'
}

Object.getOwnPropertyNames(obj)   // ['age', 'title']

JSON.stringify(obj)  // {"age":18,"title":"Engineer"}

generator函数
: 解决异步深度嵌套
在Javascript中,一个函数一旦开始执行,就会运行到最后或遇到return时结束,运行期间不会有其它代码能够打断它,也不能从外部再传入值到函数体内而Generator函数(生成器)的出现使得打破函数的完整运行成为了可能,其语法行为与传统函数完全不同Generator函数是ES6提供的一种异步编程解决方案,形式上也是一个普通函数,但有几个显著的特征:
– function关键字与函数名之间有一个星号 “*” (推荐紧挨着function关键字)
– 函数体内使用 yield 表达式,定义不同的内部状态 (可以有多个yield)
– 直接调用 Generator函数并不会执行,也不会返回运行结果,而是返回一个遍历器对象(Iterator Object)
– 依次调用遍历器对象的next方法,遍历 Generator函数内部的每一个状态

function* generator(){
    yieId 'welcome';
    yieId 'to';
    yieId 'shanghai';
    return 'wo';
} 

let  g1 = generator();
console.log(g1); // 返回的是一个Iterator对象

console.log(g1.next()); // {value: "welcome", done: false},value 表示返回值,done 表示遍历还没有结束
console.log(g1.next()); // {value: "to", done: false},value 表示返回值,done 表示遍历还没有结束
console.log(g1.next()); // {value: "shanghai", done: false},value 表示返回值,done 表示遍历还没有结束
console.log(g1.next()); // {value: "wo", done: true},value 表示返回值,done 表示遍历结束
console.log(g1.next()); // {value: "undefined", done: true},value 表示返回值,done 表示遍历结束

--------
for ..of 可以自动遍历generator,但是不会遍历return,
解构赋值,也是不会遍历return的
---------
for(let a of generator){
console.log(generator); //welcome to shanghai
}
let [a,b,c]=generator();
console.log(generator); //welcome to shanghai undefined
let [a,...b]=generator();
console.log(a); //welcome 
console.log(b); // to shanghai 

十一、async 、await

async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。另外还有一个很有意思的语法规定,await 只能出现在 async 函数中

如果需要通过 await 来调用一个 async 函数,那这个调用的外面必须得再包一个 async 函数,然后……进入死循环,永无出头之日……

这个问题的关键在于,async 函数是怎么处理它的返回值的!

**async 函数返回的是一个 Promise 对象。**从文档中也可以得到这个信息。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

async 函数返回的是一个 Promise 对象,所以在最外层不能用 await 获取其返回值的情况下,我们当然应该用原来的方式:then() 链来处理这个 Promise 对象,

读取文件例子与上面的Promise ,generator比较


const fs = require('fs');
const readfile = function(fileName){
  return new Promise((resolve,reject)=>{
	fs.readFile(fileName,'utf-8',(err,data)=>{
	      if(err){
	      	console.log(err);
	      }else{
	        console.log(data);
	      }
		});
	});
}
---------------------------
//Promise 的方法

readFile(fileName1).then((res)=>{
    console.log(res.toString());
    return readFile(fileName2);
}).then((res)=>{
	 console.log(res.toString());
    return readFile(fileName3);
}).then((res)=>{
	 console.log(res.toString());
});
---------------------------
//generator的方法

function* gen(){
   yieId readFile(fileName1);
   yieId readFile(fileName2);
   yieId readFile(fileName3);
}
let g1=gen();
g1.next().value.then(res=>{
   console.log(res.toString());
   return g1.next().value;
})then(res=>{
   console.log(res.toString());
   return g1.next().value;
})then(res=>{
   console.log(res.toString());
   return g1.next().value;
});
---------------------------
async 的方法

async function fn(){
	 let f1 =    await readFile(fileName1);
 	console.log(f1);
	let f2 =	await readFile(fileName2);
    console.log(f2);
	let f3 =	await readFile(fileName3);
   console.log(f3);
}
fn();

async的特点:

  • await 只能放到 async 中
  • 相比 genrator 语义化
  • await 后面可以是promise 对象,也可以是 数字,字符,布尔值
  • async 返回的是一个 promise 对象
  • 只要 await 语句后面 promise 状态 为 reject ,整个函数会中断执行

如何解决 async 函数中抛出错误,影响后续代码”:

  • try{
    }catch(e){
    }
async function fn(){
	try{  
		await Promise.reject('出问题');
	   }catch(e){ }	
	let a =await  Promise.resolve('aaa');
}
fn().then(res=>{
	console.log(res);
});
  • promise 本身
async function fn(){
	await Promise.reject('出问题').catch(err=>{
		console.log(res);
	});
	let a =await  Promise.resolve('aaa');

}
fn().then(res=>{
	console.log(res);
});

建议:网络请求容易出现问题,任何有 async 的地方最好加上 try—catch

async function fn(){
	try{  
	let f1 =    await readFile(fileName1);
	let f2 =	await readFile(fileName2);
 	let f3 =	await readFile(fileName3);
	 }catch(e){ }	
	
 	console.log(f1);	
    console.log(f2);
    console.log(f3);
}
fn();

十二、数据结构 Set与WeakSet

Set 类数组,里面不允许有重复值。
我们可以利用这一唯一特性进行数组的去重工作。

let set = new Set([1, 2, 2, 3, 4, 3, 5])
console.log( set); //Set { 1, 2, 3, 4, 5 }
 多数组的合并去重
let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let set7 = new Set([...arr1, ...arr2])
console.log( set7)// Set { 1, 2, 3, 4, 5, 6 }

setArr.add(); 添加
setArr.delete(); 添加
setArr.has(); 检测,有没有
setArr.size 查看个数
setArr.clear(); 清空

数组的去重:

let Arr =[1,2,3,4,4,4];
let newArr =[...new Set(Arr)];
console.log(newArr);// 1,2,3,4

let a = new Set([1,2,3]);
set = new Set([...a].map(val=>val*2));
console.log(set);//Set{2,4,6}

Set 存储数组
WeakSet 存储 json 对象,没有size

十三、数值(数字)的变化

二进制( Binary ):前面加 0b

let number = 0b010101;//21

八进制(octal)0o 数字0加字母o

let number = 0o666;//438

十六进制:#ccc

判断一个值是否是数字
以前:

  • Number ----- parseInt() 、parseFloat()
    es6 :
  • Number.isFinite();

Number.isInteger(); 判断数字是否为整数

安全整数:2的53次方减一 , -(253-1)-----(253-1)
Number.isSafeInteger();

Math 新增:

Math.trunc() 截断。截取(只保留整数部分)

Math.trunc(4.22) //4

Math.sign(); 判断一个数是整数,负数,还是0

Math.sign(-5)   //-1
Math.sign(5)   //1
Math.sign(0)   //0
Math.sign(-0)	//-0
Math.sign(abc)	//NaN

Math.cbrt() 立方根

Math.cbrt(27)  // 3

十四、es2018 (es9)新增的东西

命名捕获
语法:(?<名字>)

之前:

let str ='2020-02-22';
let reg =/(\d{4})-(\d{2})-(\d{2})/;
let dataArr =str.match(reg);
let year = dataArr[1];
let year = dataArr[2];
let year = dataArr[3];

let str ='2020-02-22';
let reg =/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let {year,month,day}=str.match(reg).groups;

十五、proxy

es 6 proxy:

  • 代理
  • 扩展(增强)对象的一些功能
    Proxy 是 ES6 中新增的功能,它可以用来自定义对象中的操作。
    比如:在vue 中拦截
  • 预警,上报,扩展功能,增强对象

语法:
new Proxy(target , handler);
let obj = new Proxy (被代理的对象,对代理对象做什么操作);

   handler{
 		set(){}------------------设置对象时的操作
 		get(){} ------------------获取对象时的操作
 		deleteProperty(){}------------------删除对象时的操作
 		has(){}------------------询问有没有这个对象时的操作
 		apply(){}------------------调用函数处理
 		.......
 	  }
   
let obj = {
  name :'ling'
}
//拦截,您访问了name
obj.name // ling

-------

let obj = {  //未暴露给用户
  name :'ling'
}
let newobj =new Proxy(obj,{  //代理obj
	get(target,property){
	console.log(target,property); //target操作对象obj,property 获取的对象 name/aaa
	return target[property];
	}
);
newobj.name;
newobj.aaa;
----------
let obj = {
  name :'ling'
}
let newobj =new Proxy(obj,{  
	get(target,property){
	console.log(`您访问了${property}属性`); 
	return target[property];
	}
);

console.log(newobj.name);

------------
let obj = {
  name :'ling'
}
let newobj =new Proxy(obj,{  
	get(target,property){
     	if(property in target){
		 console.log(`您访问了${property}属性`); 
			return target[property];
		}else{
		    console.warn(`${property }不在此对象上`); //警告
		    throw new ReferenceError(`${property }不在此对象上`); //抛出一个错误
		}
	
	}
);

console.log(newobj.name);//您访问了name属性 ling
console.log(newobj.aaa);//aaa不在此对象上   aaa不在此对象上


apply() :

function fn(){
   return '我是函数';
}
let newfn=new Proxy(fn,{
    apply(){
	   return '函数吗?'
	}
});
console。log(newfn()); //函数吗

Reflect
反射,拦截执行通过用反射。

function sum(){
   return '我是函数';
}
let newSum=new Proxy(sum,{
    apply(target,context,args){ //target 对象, args 参数数组, context 
	 return Reflect.apply(...arguments)*2;
	}
});
console。log(newSum(2,3)); // 10

Reflect.apply(调用的函数,this指向,参数数组)

alert(Math.cell(4.6)); //5

let res= Reflect.apply(Math.cell,null,[9.8]); //10

‘assign’ in Object ----> Reflect.has(Object,‘assign’);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值