ES6梗概二

ES6 梗概二


es6 和 es5 对象的属性和值的写法

es6 面向对象继承

编程范式:命令式编程/声明式编程(如 vue 中 v-for 的渲染)

编程范式:面向对象编程(第一公民:对象)

函数式编程 (第一公民:函数)

面向对象

分工方便

高内聚,低耦合

模块化

1.一般按照功能拆分(可以是一个按钮,可以是模态框)

2.分工更细更明确,项目好管理

3.复用性强

js 社区提出了模块化的解决方法

requirejs AMD 规范

requirejs.org

非同步加载规范,允许回调函数

requirejs(['xxx','xxx2']),function(mod1,mod2){}

seajs CMD 规范

seajs.github.io/seajs

用于前端

seajs.use('xxx',function(xxx){})

**    nodejs Commonjs 规范**

**    **** **   模块可以多次加载,但只是第一次加载时运行,然后运行的都在缓存中,如果想得到更新的,需要清除缓存。

加载是同步加载

给后台用

**        **

模板字符串

<font style="color:#FF0000;">XXXx ${变量名} DDDDD</font>

字符串方法

查找字符串的内容

str.includes('c') true | false

判断字符串以什么开头、结尾

str.startsWith('ab')

str.endsWith('c')

重复输出字符串

str.repeat(n)–n 代表重复的次数

rest 运算符

也被称为: 扩展运算符、三点运算符

语法 ...rest

1.数组解析成逗号隔开的数据,主要用于复制数组

var arr1 = [1,2,3];

var arr2 = [...arr1];

**arr1.push(…arr2) –push 中可以用可变的参数,就是将 arr2 中每个元素一个一个的添加到 arr1 中。****push 的参数不能是一个数组,不然该数组只是一个 arr1 的一个元素。只能写为扩展运算符的形式**

2 解构配合使用进行赋值, ...运算符必须的是最后一个

let [a,...b] = [1,2,3];

let {c,<font style="background-color:#FFFAA5;">...d</font>} = {c:1,<font style="background-color:#FFFAA5;">d:2,e:3</font>}

解构赋值

在对复杂类型进行解构的时候,可复制了一份   变量的引用

**    ****  const {index} = e.currentTarget.dataset;**

–相当于  const index = e.currentTarget.dataset.index

**      let {tabs} = this.data;**

**    ****    –相当于  **let tabs = this.data.tabs

普通深拷贝写法

let tabs = JSON.parse(JSON.stringify(this.data.tabs))

连续的解构赋值

**            **

- **连续解构并改名**
    * **     **![](https://cdn.bazijun.top/yuqueImg/FjVdsmKq6FY8NSiUdNzhYEQZP7AL.png) **     **

函数参数 解构赋值 => 就是对传入的 object 参数 (提前) 进行解构赋值

使用一个{ .. }进行对象解构也可用于被命名的函数参数,这时它是同种类的隐含对象属性赋值的语法糖:

1
2
3
4
5
6
7
8
9
10
11
function foo({ a, b, c }) {
// 不再需要:
// var a = obj.a, b = obj.b, c = obj.c
console.log(a, b, c);
}

foo({
c: [1, 2, 3],
a: 42,
b: "foo",
}); // 42 "foo" [1, 2, 3]

箭头函数没有 arguments 对象,可以用 …运算符得到所有参数

1
2
3
4
let fun = (...a) => {
console.log(a);
};
fun(1, 2, 3);

通过解构赋值 置换连个元素得位置

对象的扩展

跟数组的扩展其实一样, 属性名相同就是覆盖修改,不同就是新增

合并数组 数组拼接

1
2
3
var arr1 = [1,2,3]
var arr2 = [4,5,6]
[...arr1,...arr2]

–数组的方法

Array.from

Array.of

Array.includes

=

Array.includes 和 Array.indexOf 的区别

都可以判断数组和字符串 效果都相近

但是在 if 语句的使用中 更推荐 includes 因为它 会根据是否包括直接返回 true 或 false 并且是包含就是 一部分相同即可。

而 indexOf 则需要通过 返回的 index 下标再判断。第一个满足的下标 返回是下标 0,不满足返回 -1 这完全不利于 if 的条件判断。

=

generator

generator 生成器 就是一种函数

普通函数:一旦调用,一直执行,不会暂停,执行完了或者遇到 return 才结束,遇到错误也会停止

generator,中间可以暂停,可以把函数分成好几段执行

箭头函数不能改成 generator

yield 间隔符

 1.暂停函数执行 配合 next 继续执行

2.返回中间的结果

3.传参

let res = yield 111;

res 就是 next 执行前,执行函数传递的参数

111  next 执行后,返回的值。

–基础使用–

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function* show() {
alert(1);
yield 111; //暂停
var a = 2;
alert(a);
yield 222;
var b = 3;
alert(b);
return b;
}

let obj = show(); //返回值就是一个generator对象,这个对象可以控制函数的进程

console.log(obj.next()); //返回yield 后面的结果
console.log(obj.next()); //返回第二个yield 后面的结果
console.log(obj.next()); //return b

–传参–

1
2
3
4
5
6
7
8
9
10
11
12
13
function* show(n) {
alert(n);
let res = yield 111; //暂停
alert(res);
let res2 = yield 222;
alert(res2);
}

let obj = show(89); //返回值就是一个generator对象,这个对象可以控制函数的进程

console.log(obj.next(2)); //这里传值无效, 返回 yield后面的值
console.log(obj.next(4)); //这里传的参数给了 res,相当于把参数4传递给了yield 111的结果
console.log(obj.next(8)); //这里传的参数给了 res2,相当于把参数8传递给了yield 222的结果

–  传参 2 –

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* show(n) {
alert(n);
let res = yield n; //暂停
res++;
alert(res);
let res2 = yield res;
alert(res2);
}

let obj = show(1); //返回值就是一个generator对象,这个对象可以控制函数的进程
let y1 = obj.next().value; //执行第一次 -第一次为 1
y1++;
let y2 = obj.next(y1).value; //执行第二次 -第二次为 3
y2++;
obj.next(y2); //执行第三次 -第三次为4

promise

  • 对异步操作进行封装
  • new -> 构造函数(1.保存了一些状态信息、2.执行传入的函数)
  • 在执行传入的回调函数时,会传入两个参数 resolve,reject,这两参数本身也是函数
  • 分离异步请求的。请求 与 (数据)处理的操作

https://blog.csdn.net/taowuhua0505/article/details/106796330

Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的属于微任务 setTimeout 定时器等也是异步任务属于宏任务。 执行顺序:同步任务(1)>微任务(2)>宏任务(3)

**  **** 1.**Promise 可以把 Callback hell(回调深渊)一层层嵌套的 callback 变成 .then().then()…,从而使代码编写和阅读更直观

2 .catch()。处理 reject 参数的错误信息。

3.Promise 的 then 方法可以返回上一个 Promise 的回到结果,也可以 return 一个新的 Promise,从而实现链式调用

then 函数传入两个参数,第一个参数代表成功的回调(resolve),第二个参数代表失败的回调(reject)

4.Promise 的 all([ … ])。括号中是数组,数组中可执行多个请求,只有所有请求都成功了,才调用 .then()方法。并且 then 回调的 results 值也是个数组。

–第一个请求回调的参数 results[0] 、第二个请求回调的参数 results[1] …


>>写法演变

–最直接写法

–new Promise((res,rej) => res();rej())的简写

–省略掉 Promise.resolve/reject

–reject 再 简写 不用 return 用 throw

then 的参数必须使用函数,使用基本数据类型会出现值穿透。不用 resolove 可以使用null代替

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('success')
reject("fail");
}, 1000);
})
.then(null, (rejected) => {
console.log("rejected===" + rejected);
return new Promise((resolve, reject) => {
reject(100);
});
})
.then(null, (reject) => {
console.log("=====" + reject);
});

通过上面几个问题能感受到 Promise 更像一个保存状态的魔法罐,只要状态改变就可以就能一直传递下去,并且状态持久的保存在自己身上,随时都可以 then 函数的调用。其次状态是不可逆的,只能从 pending 转化为 fulfilled 或者 rejected。总结一句话就是状态就是 Promise 的灵魂所在,状态使用 resolve 或者 reject 管理的。接下来通过几个例子来理解 Promise


进行中

已成功 resolve

已失败 reject

– ajax 实例 –

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function ajax() {
new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
resolve(xhr.responseText);
} else {
reject(xhr.status);
}
}
};
});
}

async await (外异内同)

https://www.jianshu.com/p/73b070eebf50

详解我能看懂的: https://blog.csdn.net/weixin_39911475/article/details/111522143

=

forEach 不兼容 async await 还是 会出现 请求顺序乱的问题

推荐 for of <font style="color:#4F4F4F;">for (let item of larr) </font>  或 for

=

** async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。**

async

async 用来表示函数是异步的,定义的函数会返回一个 promise 对象,可以使用 then 方法添加回调函数。

1
2
3
4
5
6
async function demo01() {
return 123;
}
demo01().then((val) => {
console.log(val); // 123
});

若 async 定义的函数有返回值,return 123;相当于 Promise.resolve(123),没有声明式的 return 则相当于执行了 Promise.resolve();

1
2
3
4
5
6
async function show() {
let ajaxRes1 = await ajax();
let ajaxRes2 = await ajax({ data: { ajaxRes1 } });
let ajaxRes3 = await ajax({ data: { ajaxRes2 } });
return ajaxRes3;
}
  • 箭头函数:参数前面加   async

async await 可以说是对 promise 的优化;

–async 关键字:

在事件前加上   关键字 async  即可将其定义为一个异步事件;

async 返回一个 promise 对象;

async 函数工作在主线程,同步执行,不会阻塞界面渲染;


–await 关键字

awiait 只能在 async 函数内部使用:不能放在普通函数中。

awiati 关键字后面跟 promise 对象

await 只关心异步过程成功的消息 resolve(data)

  • 如果要获取错误信息
  • 使用 try catch **,把 awiait 写在 try 里面,错误信息再写到 catch 中  **

await 执行失败   就不会向后执行

1
2
3
4
5
6
7
async function asy() {
const ms = await takeTimes(1000);
const ms1 = await takeTimes(1000);
const ms2 = await takeTimes(1000);
console.log(ms + ms1 + ms2);
}
asy();

上面代码中,我们使用await 去阻塞 takeTimes,让他执行完当前步骤后然后这个步骤所花的时间,然后依次执行第二第三次步骤,最后把累计花费的时间累加就是这个事件所花的时间了,

坑与技巧

= 简洁写法

= 使用 await 等待 promise.all 并发请求

**= for await **

–小程序如果中使用 es7 的 async  需导入   此 js  且每个使用 async 的页面里 js 都得单独导入 (现在增强编译已经支持了)

1
import regeneratorRuntime from "路径/runtime";

高级数组函数

filter

  • find 函数   是返回符合测试条件的第一个数组元素的值
  • 而 fillter,就算过滤出只有一条数据,返回的是一个数组。

=

filter 参数中 可以是 数量类型    比如 Number Boolean String 因为这些本身也都是方法。

相当于可以直接过滤数据类型

const compact = (arr) => arr.filter(Boolean); // 从数组中移除 falsey 值。

reduce

可以配合一起使用   就是函数式编程(类似链式编程)

==

map

  • map 函数第二参数可以改变 this 指向
  • 只要需要 return 的函数   都不会改变原数组
  • 但是数组中还要其他引用数据类型。直接修改 item 的键值,就会改变原来数组了,但是如果 直接赋值修改 item 则不会。 
  • 基本数据类型就是除了 Object 外的 他们的赋值本质都是拷贝
  • 而被拥有引用数据类型值的变量赋值则是 对 Object 值本身的引用,而非对赋值变量的引用。
  • 就是说 你可以通过存有某对象引用的变量,来修改这个对象本身,因为不是拷贝,是引用(共享)。
  • 修改后的值会共享到同样引用此对象的变量上面。
  • 但是你对这个变量重新赋值时,并不代表对引用的对象赋值,只是单纯的给这个变量赋值。
  • 引用的对象 还是 原样一点没变,只是重新赋值后的变量的值 变成了其他的值,
    其他引用这个对象的变量,值依然是那个对象,不会改变的。
  • 这很重要,不要被骗了。
    1. 比如:
    2. 两种方法 深拷贝
    3. 或者用扩展运算符
  • 如果没有返回值,数组中的元素都会变为 undefined
  • map 函数之后,数组元素个数不变,按照一定的条件转换,数组元素也会发生了变化。filter 函数之后,数组元素个数可能发生了改变,但是数组元素不会发生改变
    • map 改变元素,但数组个数不变、filter 数组个数会改变,元素本身不改变。

sort

<会改变原数组>

排序

  • a - b 从小到大
  • b - a 从大到小


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!