复习ES(6-11)语法之ES8
目录
async/await
async 函数是 Generator 函数的语法糖。
async 函数对 Generator 函数的改进,体现在以下四点:
-
内置执行器。
Generator 函数的执行必须靠执行器,所以才有了 co 模块,而 async 函数自带执行器。也就是说, async 函数的执行,与普通函数一模一样,只要一 行。 -
更好的语义。
async 和 await ,比起星号和 yield ,语义更清楚了。 async 表示函数里有异步操作, await 表示紧跟在后面的表达式需要等待结果。
-
更广的适用性。
co 模块约定, yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以是 Promise 对象和原始类型的值(数值、字 符串和布尔值,但这时等同于同步操作)。
-
返回值是 Promise。
async 函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用 then 方法指定下一步的操作。 进一步说, async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖
// function foo() {
// return "imooc";
// }
// console.log(foo()); // imooc
async function foo() {
return "imooc";
}
console.log(foo()); // Promise { 'imooc' }
有这样一个异步定时器1秒后输出1,在async函数里正常调用,结果则会先输出1再输出2
function timeout() {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
});
}
async function foo() {
timeout();
console.log(2);
}
foo(); //先输出2再输出1
如果加上await,就会先等待输出定时器的内容再输出2
async function foo() {
await timeout();
console.log(2);
}
foo(); //先输出1再输出2
async
函数内部return
语句返回的值,会成为then
或者catch
方法回调函数的参数。
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(1);
// resolve("success");
reject("fail");
}, 1000);
});
}
async function foo() {
return await timeout();
}
foo()
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
await用于ajax请求,请求顺序a→b→c
function ajax(url, callback) {
// 1、创建XMLHttpRequest对象
var xmlhttp
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else { // 兼容早期浏览器
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
}
// 2、发送请求
xmlhttp.open('GET', url, true)
xmlhttp.send()
// 3、服务端响应
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var obj = JSON.parse(xmlhttp.responseText)
// console.log(obj)
callback(obj)
}
}
}
function request(url) {
return new Promise(resolve => {
ajax(url, res => {
resolve(res)
})
})
}
async function getData(){
const res1 = await request('static/a.json')
console.log(res1)
const res2 = await request('static/b.json')
console.log(res2)
const res3 = await request('static/c.json')
console.log(res3)
}
getData()
// {a: "我是A"}
// {b: "我是B"}
// {c: "我是C"}
对象扩展
Object.values()
Object.values()
可以得到该对象的属性值集合
const obj = {
name: "zzz",
age: 18,
level: 1,
};
const res = Object.keys(obj).map((key) => obj[key]);
console.log(res); // [ 'zzz', 18, 1 ]
console.log(Object.values(obj)); // [ 'zzz', 18, 1 ]
Object.entries()
Object.entries()
可以得到该对象的{ key:value }的集合
console.log(Object.entries(obj)); // [ [ 'name', 'zzz' ], [ 'age', 18 ], [ 'level', 1 ] ]
for (let [key, val] of Object.entries(obj)) {
console.log(`${key}:${val} `);
}
Object.getOwnPropertyDescriptors():对象属性描述符
Object.getOwnPropertyDescriptors()返回指定对象所有自身属性(非继承属性)的描述对象。如果是ES5的Object.getOwnPropertyDescriptor()
方法会返回某个对象属性的描述对象
const obj = {
name: "zzz",
};
const desc = Object.getOwnPropertyDescriptors(obj);
console.log(desc);
// {
// name: {
// value: 'zzz',
// writable: true,
// enumerable: true,
// configurable: true
// }
// }
- value:属性值
- writable:是否可以修改
- configurable:是否可以通过delete 删除该属性
- enumable:是否可以枚举该属性
可以通过Object.defineProperty对对象上的某一个属性添加这4样属性描述符
const obj = {};
Reflect.defineProperty(obj, "name", {
value: "zzz",
writable: false, // 不可写
configurable: false, // 不可删除
enumerable: true, // 可遍历
});
console.log(obj); // { name: 'zzz' }
obj.name = "zzzz";
console.log(obj); //{ name: 'zzz' }
delete obj.name;
console.log(obj); // { name: 'zzz' }
字符串扩展
- String.prototype.padStart()
- String.prototype.padEnd()
这2个方法是用于字符串补全长度。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()
用于头部补全,padEnd()
用于尾部补全。
padStart()
和padEnd()
一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。如果省略第二个参数,默认使用空格补全长度。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
padStart()
的常见用途是为数值补全指定位数。
//yyyy-mm-dd
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const day = now.getDate().toString().padStart(2, "0");
console.log(`${year}-${month}-${day}`);
//加密手机号
const tel = "13212312312";
const newTel = tel.slice(-4).padStart(tel.length, "*");
console.log(newTel); // *******2312
尾逗号
允许函数参数列表使用尾逗号。
function f(p) {}
function f(p,) {}
(p) => {};
(p,) => {};
这样改动的好处有两点
- 重新排列项目更简单,因为如果最后一项更改其位置,则不必添加和删除逗号。
- 可以帮助git等版本控制系统跟踪实际发生的变化,在查看代码改动、合并代码的时候,少报一些无用信息。