es6+一些新特性

es7+特性一览
es6+一些新特性_第1张图片

写这篇文章是读了微信的一篇文章(下面有链接,上面图片也是窃他的)结合自己的理解和测试而得,主要是做一个学习的记录,也给想了解js新特性的朋友提供一些参考,文章较长,有耐心的你应该可以读完!当然文章有错误的地方望大家不吝指出,谢谢!

ES7、ES8、ES9、ES10新特性大盘点

你还能学,要不然我扶你一把?


  • inclues

arr.includes(valueToFind[, fromIndex]) 从fromIndex (可选)索引处开始查找
valueToFind。如果为负值,则按升序从 array.length + fromIndex 的索引开始搜 (即从末尾开始往前跳
fromIndex的绝对值 个索引,然后往后搜寻)。默认为 0。

indexOf: 一是不够语义化,要先找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判

[NaN].indexOf(NaN)// -1

检测数组是否拥有某个元素,替代indexOf(x) > -1

[1,2,3].includes(1) //true
[1,2,3].includes(1,1)  //false,第二个参数表示查找的起始位置
[3,45,6].includes(45,-2) //true -2+3 = 1开始向右搜索,包括下标为1
[3,45,6].includes(45,-20) //true 当计算结果小于0时,搜索整个数组

str.includes(searchString[, position]) 参数同上

检测字符串是否拥有某个元素

"hsfjkshfjksfk".includes('') //true
"hsfjkshfjksfk".includes('hsf') //true
"hsfjkshfjksfk".includes('hsf',1) //false
"hsfjkshfjksfk".includes('sfk',5) //true
"北京欢迎您".includes('欢',0) //true
"北京欢迎您".includes('欢',-1) //true 起始索引为负数时查找全数组
"sfjgf".includes('SF') //false

  • find: 不改变数组,返回第一个匹配的元素

arr.find(callback[, thisArg]) callback 在数组每一项上执行的函数,接收 3 个参数:
element 当前遍历到的元素。
index可选: 当前遍历到的索引。
array可选 : 数组本身。
thisArg可选: 执行回调时用作this 的对象。 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。

[1, 4, -5, 10].find((n) => n < 0) // -5
[1, 5, 10, 15].findIndex(function(value) {  return value > 9;}) // 2
[NaN].findIndex(y => Object.is(NaN, y)) // 0
// MDN上的找质数函数
function isPrime(element, index, array) {
  var start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) {
      return false;
    }
  }
  return element > 1;
}
console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5

注意:通过find callback删除的元素依然可以被fin遍历到,返回undefined

var a = [3,4,'',,,8];
a.find(function(value,index,arr) { if(index === 5) delete arr[index] }) //undefined
a //[3, 4, "", empty × 3]
a.find((a,i) => i===5) //undefined
// 利用pop()对数组有些影响,但结果是一样的,这是没找到返回undefined
var a1 = [3,4,'',,,8];
a1.find(function(value,index,arr) { if(index === 5) arr.pop() }) //undefined
a1 //[3, 4, "", empty × 2]
a.find((a,i) => i===5) //undefined

  • findIndex

返回找到数组的索引,用法同find

[3,4,5,6].findIndex((ele,index) => index>1&&ele>5) //3
[{name: 'li',age: 22},{name: 'wang', age: 23}].findIndex(person => 
	person.name === 'wang'
) // 1

  • 求幂运算符 **

不细说,如下:

2**10 //1024 和Math.pow等同
Math.pow(2,10) //1024

  • async/await

这对难兄难弟把异步promise简化了,写异步代码就像写同步代码一样,
需要注意的是:await需要配合async使用,单独使用async的函数会被包装成promise,可以使用.then什么的

async function foo () {
  try {
      let response1 = await fetch('https://blog.csdn.net/')
          console.log(response1)
      let response2 = await fetch('https://juejin.im/')
          console.log(response2)
       } catch (err) {
           console.error(err)
       }}
foo()
//另外一个demo
async function foo () {
  return '花蜻蜓'
}
foo().then(val => {
    console.log(val) // 花蜻蜓
})

async/await内容相对较多,这里只举了一个小小栗子,我其他博文也有介绍,另 MDN await


  • Object.values(),Object.entries()

es5引入了Object.keys()方法用于遍历对象的(可遍历的)键值,这两个方法为es8引入
.values(): 返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for…in循环的顺序相同 ( 区别在于 for-in循环枚举原型链中的属性 )。
.entries(): 返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

Object.values({a:1, b:45, c:'xx'}) //[1, 45, "xx"]
Object.values({100: 'x',4: '5', 8: 90}) //["5", 90, "x"]
Object.values('say hello') //["s", "a", "y", " ", "h", "e", "l", "l", "o"]
Object.entries({a:1, b:45, c:'xx'}) //[["a", 1],["b", 45],["c", "xx"]]// 注意 键加上了双引号
Object.entries({1:1, 8:45, 6:'xx'}) //[["1", 1],["6", "xx"],["8", 45]]
Object.entries('say')[["0", "s"],["1", "a"],["2", "y"]]
// 优雅地遍历键值
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}

需要注意的是,
如果对象键值是数字的话,会按从小到大的顺序输出。
字符串也被切割了(字符串也是对象呀),
类似String.splite()
‘say hello’.split(’’) // [“s”, “a”, “y”, " ", “h”, “e”, “l”, “l”, “o”]


  • pdStart与padEnd

es8新增,允许将空字符串或其他字符串添加到原始字符串的开头或结尾
str.padStart(targetLength [,padString])
targetLength 当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
padString 可选 填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的缺省值为 " "

str.padEnd(targetLength [, padString]): 参数同上,不再做说明,详情见例子

// padStart
'hqt'.padStart(5) //"  hqt",默认以‘’填充
'hqt'.padStart(5,'yqg') //"yqhqt"
'hqt'.padStart(10,'yqg') //"yqgyqgyhqt"
'hqt'.padStart(1,'yqg') //"hqt",目标长度低于字符串长度时,返回字符串本身
// padEnd
'花里胡哨'.padEnd(1) //"花里胡哨"
'花里胡哨'.padEnd(6) //"花里胡哨  "
'花里胡哨'.padEnd(6,'花蜻蜓') //"花里胡哨花蜻"
'花里胡哨'.padEnd(11,'花蜻蜓') //"花里胡哨花蜻蜓花蜻蜓花"

  • Object.getOwnPropertyDescriptors()/Object.getOwnPropertyDescriptor()

该方法会返回某个对象属性的描述对象(descriptor),返回可读,可配置等相关属性

const obj = {
  name: '花蜻蜓',  
  get bar () {
      return 'abc'  
  }}
console.log(Object.getOwnPropertyDescriptors(obj))
//bar:
//    configurable: true
//    enumerable: true
//    get: ƒ bar()
//    set: undefined
//name:
//    configurable: true
//    enumerable: true
//    value: "花蜻蜓"
//    writable: true

该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题

const source = {
  set foo (value) {
    console.log(value)  
  },  
  get bar () {
    return '花蜻蜓'  
}}
const target1 = {}
Object.assign(target1, source)
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'))
//{value: undefined, writable: true, enumerable: true, configurable: true}
target1
//{foo: undefined, bar: "花蜻蜓"}

  • for await…of

for of方法能够遍历具有Symbol.iterator接口的同步迭代器数据,但是不能遍历异步迭代器。
ES9新增的for await of可以用来遍历具有Symbol.asyncIterator方法的数据结构,也就是异步迭代器,且会等待前一个成员的状态改变后才会遍历到下一个成员

// for of遍历 google控制台测试的,多余的信息我也给出来了
function Gen (time) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve(time)
    }, time)
  })
}
async function test () {
  let arr = [Gen(2000), Gen(100), Gen(3000)]
  for (let item of arr) {
    console.log(Date.now(), item.then(console.log))
  }
}
test()
//VM568:12 1576049914690 Promise {}
//VM568:12 1576049914691 Promise {}
//VM568:12 1576049914691 Promise {}
//Promise {: undefined}
//100
//2000
//3000

//for await of
//....其它代码不变
async function test () {
  let arr = [Gen(2000), Gen(100), Gen(3000)]
  for await (let item of arr) {
    console.log(Date.now(), item)
  }
}
test()
Promise {<pending>}
//VM588:11 1576050067429 2000
//VM588:11 1576050067430 100
//VM588:11 1576050068430 3000

  • Promise.prototype.finally()

在promise的then或catch都会进入的流程,避免了同样的代码在then和catch中各写一遍

axios.get(xxxx)
.then(res => {})
.catch(err => {})
.finnally(() => { console.log('无论如何我都会被打印') })

  • Array.prototype.flat() Array.prototype.flatMap()

es10新增, var newArray = arr.flat([depth])
depth 代表深度(default: 1)
扁平数组的api,其他不说就是香!
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组
var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
// return element for new_array
}[, thisArg])
callback 可以生成一个新数组中的元素的函数,可以传入三个参数:
currentValue 当前正在数组中处理的元素
index可选 数组中正在处理的当前元素的索引。
array可选 被调用的 map 数组
thisArg可选 执行 callback 函数时使用的this 值

//flat()
{s: {}, q: 1}
[1,3,4,5,[45]].flat() //[1, 3, 4, 5, 45]
[1,3,4,5,[45,[3]]].flat() //[1, 3, 4, 5, 45, Array(1)]
[1,3,4,5,[45,[3]]].flat(2) //[1, 3, 4, 5, 45, 3]
// 移除数组的空项
[1,3,,,,6].flat() //[1, 3, 6]
// 一层的数组,concat+扩展运算符   或者   reduce+concat
[].concat(...[1,2,[3,4]]) //[1, 2, 3, 4]
[1,2,3,4].reduce((acc, val) => acc.concat(val), []); //[1, 2, 3, 4]
//多层数组,cancat+isArray+reduce+递归(recursivity)
function flatDeep(arr) {
   return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val) : val), []);
};
flatDeep([1,2,[3,[4,5]]]); //[1, 2, 3, 4, 5]

//flatMap() flat 与map的结合体
[1,2,3,4].map(x=> [x*2])[[2], [4], [6], [8]]
[1,2,3,4].flatMap(x=> [x*2]) //[2, 4, 6, 8]可以扁平一层
[[1,3],'',[7,9]].flatMap(x => x) // [1, 3, "", 7, 9]
[[1,3],'',[7,9]].flatMap(x => x!=='') //[true, false, true]

  • Object.fromEntries()

前面提到entries,即将对象变为[[“键”:“值”],…]的二维数组,那么此Api就是它的逆向操作。

Object.fromEntries(Object.entries({a:1,b:2})) //{a: 1, b: 2}
//es10之前,对对象键值进行一些筛选
const obj1 = {name: 'hqt',age: 20}
const arr = Object.entries(obj1).filter(([key,value]) => key === 'age')//[["age", 20]]
let obj3 = {}
for([key,val] of arr){
	obj3[key] = val
}
obj3 //{age: 20}
//有了fromEntries,你可以把for...of循环替换成这样
obj3 = Obj.fromEntries(arr) 
//map转对象
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
Object.fromEntries(map); // { foo: "bar", baz: 42 }

  • String.trimStart 和 String.trimEnd

trim()大家不陌生吧,trimStart与trimEnd作用差不多,只是更个性化,前者去掉前面空格,后者去掉后面空格,不改变源字符串
另外trimLeft()与trimRight()作用分别和trimStart()与trimEnd()一样,或者说是他们的别名

const str = ' 花蜻 蜓 ' //str.length = 6
str.trimEnd() //" 花蜻 蜓"
str.trimStart() //"花蜻 蜓 "
str.trimLeft() //"花蜻 蜓 "
//正则,去除右边空格
str.replace(/\s+$/g, '')  //" 花蜻 蜓"

  • String.prototype.matchAll

当使用正则的.exec()如果没有g通配符,那么只会取出匹配的第一个,这个api会取出所有返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。

这两天在温习正则,就不举例子了,怕误导大家,
另MDN String.prototype.matchAll()


  • 关于try…catch

try语句包含了由一个或者多个语句组成的try块, 和至少一个catch子句或者一个finally子句的其中一个,或者两个兼有

在es10中,try…catch语句中参数变为了可选项 另外关于try的三种搭配:

  • try…catch
  • try…finally
  • try…catch…finally
function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}

另 MDN try…catch


  • Function.prototype.toString()

返回一个表示当前函数源代码的字符串。

浏览器支持不是很理想


  • 展开运算符(…)

基础用法

[...[1,3],...[45,7]] //[1, 3, 45, 7]
{...{a:1,b:3},u:9} //{a: 1, b: 3, u: 9}

var Obj = {a:1, b:5, c:'ss'}
const {c,...C1} = Obj //undefined
C1 //{a: 1, b: 5}

需要注意的是,单层嵌套时,它是浅拷贝,

var oa = {a:1,b:2}
var ob = {c:3,a:2}
var oc = {...oa,...ob}
oa.b = 'changed'
oc //{a: 2, b: 2, c: 3}
oa //{a: 1, b: "changed"}
oc.c = 'changed'
oc //{a: 2, b: 2, c: "changed"}
ob //{c: 3, a: 2}

当数组多层嵌套时,那么原数组与新数组就会相互影响了!

var oNest = {s:{a:'ss'},q: 1}
let copy1 = {...oNest}
oNest.s.a = 'chanegd'
copy2.q = 'q'
oNest
//q: 1
//s: {a: "chanegd"}
copy1
//q: 1
//s: {a: "chanegd"}
copy1.s.a = 'changed again'
//oNest
//q: 1
//s: {a: "changed again"}

你能看到文末说明你很有耐心啊,错误的地方也别忘了留言指正啊,thx!!!

你可能感兴趣的:(JS,es6+)