Array.prototype.includes()
includes() 方法用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回 false。
语法
arr.includes(valueToFind[, fromIndex])
valueToFind,需要查找的元素值。
fromIndex 可选 从fromIndex 索引处开始查找 valueToFind。如果为负值(即从末尾开始往前跳 fromIndex 的绝对值个索引,然后往后搜寻)。默认为 0。
使用 includes()只能判断简单类型的数据,对于复杂类型的数据,比如对象类型的数组,二维数组,这些是无法判断的.
如果只想知道某个值是否在数组中存在,而并不关心它的索引位置,建议使用includes(),如果想获取一个值在数组中的位置,那么使用indexOf方法。
幂运算符
console.log(2 ** 10); // 1024
幂运算符的两个*号之间不能出现空格,否则语法会报错。
Object.values()
Object.values 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
const obj = {
name: "jimmy",
age: 18,
height: 188,
};
console.log(Object.values(obj));
// [ 'jimmy', 18, 188 ]
Object.entries()
Object.entries() 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。
const obj = {
name: "jimmy",
age: 18,
height: 188,
};
console.log(Object.entries(obj));
// [ [ 'name', 'jimmy' ], [ 'age', 18 ], [ 'height', 188 ] ]
console.log(Object.entries([1, 2, 3]));
// [ [ '0', 1 ], [ '1', 2 ], [ '2', 3 ] ]
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。
const obj = {
name: "jimmy",
age: 18,
};
const desc = Object.getOwnPropertyDescriptors(obj);
console.log(desc);
// 打印结果
{
name: {
value: 'jimmy',
writable: true,
enumerable: true,
configurable: true
},
age: {
value: 18,
writable: true,
enumerable: true,
configurable: true
}
}
●value表示当前对象的默认值
●writable表示对象属性是否可以修改
●enumerable表示当前这个属性是否可以出现在对象的枚举属性中
●configurable表示当前对象的属性能否用delete删除
设置 writable: false和configurable: false,为false时,对象的name对象的值不能改变和不能被删除,打印出来还是原来的对象。
String.prototype.padStart
把指定字符串填充到字符串头部,返回新字符串。
语法
str.padStart(targetLength [, padString])
targetLength
当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
padString 可选
填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "
应用场景
日期格式化:yyyy-mm-dd的格式:
const now = new Date()
const year = now.getFullYear()
// 月份和日期 如果是一位前面给它填充一个0
const month = (now.getMonth() + 1).toString().padStart(2, '0')
const day = (now.getDate()).toString().padStart(2, '0')
console.log(year, month, day)
console.log( `${year}-${month}-${day}` )
//输入今天的日期
数字替换(手机号,银行卡号等)
const tel = '18781268679'
const newTel = tel.slice(-4).padStart(tel.length, '*')
console.log(newTel) // *******5678
String.prototype.padEnd
把指定字符串填充到字符串尾部,返回新字符串。
应用场景
在JS前端我们处理时间戳的时候单位是ms毫秒,但是,后端同学返回的时间戳则不一样是毫秒,可能只有10位,以s秒为单位。所以,我们在前端处理这个时间戳的时候,保险起见,要先做一个13位的补全,保证单位是毫秒
尾逗号 Trailing commas
ES8 允许函数的最后一个参数有尾逗号(Trailing comma)。 此前,函数定义和调用时,都不允许最后一个参数后面出现逗号。
async/await
使用 Promise 能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着 then,语义化不明显,代码不能很好地表示执行流程
async/await是比 Promise 更优雅的异步方式
前面添加了async的函数在执行后都会自动返回一个Promise对象:
function foo() {
return 'jimmy'
}
console.log(foo()) // 'jimmy'
添加async后
async function foo() {
return 'jimmy' // Promise.resolve('jimmy')
}
console.log(foo()) // Promise
foo()
async函数中使用await,那么await这里的代码就会变成同步的了,意思就是说只有等await后面的Promise执行完成得到结果才会继续下去,await就是等待。
function timeout() {
return new Promise(resolve => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000)
})
}
// 不加async和await是2、1 加了是1、2
async function foo() {
await timeout()
console.log(2)
}
foo()
使用场景
假如有这样一个使用场景:需要先请求 a 链接,等返回信息之后,再请求 b 链接的另外一个资源。下面代码展示的是使用 fetch 来实现这样的需求,fetch 被定义在 window 对象中,它返回的是一个 Promise 对象
fetch('https://blog.csdn.net/')
.then(response => {
console.log(response)
return fetch('https://juejin.im/')
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
虽然上述代码可以实现这个需求,但语义化不明显,代码不能很好地表示执行流程。基于这个原因,ES8 引入了 async/await,这是 JavaScript 异步编程的一个重大改进,提供了在不阻塞主线程的情况下使用同步代码实现异步访问资源的能力,并且使得代码逻辑更加清晰。
通过上面代码,你会发现整个异步处理的逻辑都是使用同步代码的方式来实现的,而且还支持 try catch 来捕获异常,这感觉就在写同步代码,所以是非常符合人的线性思维的。
注意点
●await 只能在 async 标记的函数内部使用,单独使用会触发 Syntax error。
●await后面需要跟异步操作,不然就没有意义,而且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。
async/await的缺陷
Async/await 让你的代码看起来是同步的,在某种程度上,也使得它的行为更加地同步。 await 关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样。它确实可以允许其他任务在此期间继续运行,但您自己的代码被阻塞
这意味着您的代码可能会因为大量await的promises相继发生而变慢。每个await都会等待前一个完成,而你实际想要的是所有的这些promises同时开始处理(就像我们没有使用async/await时那样)。
Object Rest & Spread
在 ES9 新增 Object 的 Rest & Spread 方法
const input = {
a: 1,
b: 2,
c: 3,
}
const output = {
...input,
c: 4
}
console.log(output)
// {a: 1, b: 2, c: 4}
这块代码展示了 spread 语法,可以把 input 对象的数据都拓展到 output 对象,这个功能很实用。需要注意的是,如果存在相同的属性名,只有最后一个会生效
注意点
const obj = { x: { y: 10 } };
const copy1 = { ...obj };
const copy2 = { ...obj };
obj.x.y = "jimmy";
console.log(copy1, copy2);
// x: {y: "jimmy"} x: {y: "jimmy"}
console.log(copy1.x === copy2.x);
// → true
如果属性的值是一个对象的话,该对象的引用会被拷贝,而不是生成一个新的对象。
const input = {
a: 1,
b: 2,
c: 3
}
let { a, ...rest } = input
console.log(a, rest) // 1 {b: 2, c: 3}
当对象 key-value 不确定的时候,把必选的 key 赋值给变量,用一个变量收敛其他可选的 key 数据,这在之前是做不到的。注意,rest 属性必须始终出现在对象的末尾,否则将抛出错误
for await of
异步迭代器(for-await-of):循环等待每个Promise对象变为resolved状态才进入下一步。
ES9 中可以用 for…await…of 的语法来操作
function TimeOut(time) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(time)
}, time)
})
}
async function test() {
let arr = [TimeOut(2000), TimeOut(1000), TimeOut(3000)]
for await (let item of arr) {
console.log(Date.now(), item)
}
}
test()
// 1560092345730 2000
// 1560092345730 1000
// 1560092346336 3000
for await of 环等待每个Promise对象变为resolved状态才进入下一步。所有打印的结果为 2000,1000,3000
Promise.prototype.finally()
Promise.prototype.finally() 方法返回一个Promise,在promise执行结束时,无论结果是fulfilled或者是rejected,在执行then()和catch()后,都会执行finally指定的回调函数。这为指定执行完promise后,无论结果是fulfilled还是rejected都需要执行的代码提供了一种方式,避免同样的语句需要在then()和catch()中各写一次的情况。
使用场景
loading关闭
需要每次发送请求,都会有loading提示,请求发送完毕,就需要关闭loading提示框,不然界面就无法被点击。不管请求成功或是失败,这个loading都需要关闭掉,这时把关闭loading的代码写在finally里再合适不过了