整合ES6-ES12及相关面试题整理

ES6

箭头函数

结构:

() => 1
 
v => v+1
 
(a,b) => a+b
 
() => {
  alert("foo");
}
 
e => {
  if (e == 0){
    return 0;
  }
  return 1000/e;
}

箭头函数和普通函数的区别:

  • 箭头函数是匿名函数,不能作为构造函数,不能使用NEW
  • 箭头函数不绑定arguments,取而代之用rest参数…解决
  • 箭头函数没有原型属性
  • 箭头函数不能当做Generator函数,不能使用yield关键字
  • 箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call() , bind() , apply() 。普通函数的this指向调用它的那个对象

模板字符串

var a = `123 ${first} ${last}.`

解构赋值

获取数组中的值

//从数组中获取值并赋值到变量中,变量的顺序与数组中对象顺序对应
var foo = ['one', 'two', 'three', 'four']
var [one, two, three] = foo
console.log(one) //one
console.log(two) //two
console.log(three) //three
 
//如果你要忽略某些值,你可以按照下面的写法获取你想要的值
var [first, , , last] = foo
console.log(first) //one
console.log(last) //four
 
//你也可以这样写
var a, b;
[a, b] = [1, 2]
console.log(a) //1
console.log(b) //2

//如果没有从数组中的获取到值,你可以为变量设置一个默认值
var a, b;
[a = 5, b = 7] = [1]
console.log(a) //1
console.log(b) //7

//通过解构赋值可以方便的交换两个变量的值
var a = 1
var b = 3
;[a, b] = [b, a]
console.log(a) //3
console.log(b) //1

获取对象中的值

const student = {
  name: 'Ming',
  age: '18',
  city: 'Shanghai',
}
const { name, age, city } = student
console.log(name) //Ming
console.log(age) //18
console.log(city) //Shanghai

扩展运算符

//函数调用
function sum(x, y, z) {
  return x + y + z
}
const numbers = [1, 2, 3]
console.log(sum.apply(null, numbers)) //6
console.log(sum(...numbers)) //6

//构造函数
const stuendts = ['Jine', 'Tom']
const persons = ['Tony', ...stuendts, 'Aaron', 'Anna']
console.log(persons) //["Tony", "Jine", "Tom", "Aaron", "Anna"]

//数组拷贝
var arr = [1, 2, 3]
var arr2 = [...arr,4]
arr2.push(5)
console.log(arr2) //[1, 2, 3, 4, 5]

//连接多个数组
var arr1 = [0, 1, 2]
var arr2 = [3, 4, 5]
var arr3 = [...arr1, ...arr2]
//等同于
var arr4 = arr1.concat(arr2)

//对象
var obj1 = { foo: 'bar', x: 42 }
var obj2 = { foo: 'baz', y: 13 }
var clonedObj = { ...obj1 }
var mergedObj = { ...obj1, ...obj2 }
console.log(clonedObj) //{foo: "bar", x: 42}
console.log(mergedObj) //{foo: "baz", x: 42, y: 13}

对象属性简写

let name = 'Ming',
  age = '18',
  city = 'Shanghai'
let student = {
  name,
  age,
  city,
}
console.log(student) //{name: "Ming", age: "18", city: "Shanghai"}

promise(重点说一下)

理解:
解决异步和回调地狱的一种方案
从语法上说Promise是一个构造函数
从功能上说Promise 对象用来封装一个异步操作并可以获取其结果

三种状态:
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.then()或者.catch()

两种状态改变:
pending 变为 fulfilled
pending 变为 rejected

流程:
在这里插入图片描述
基本使用:

//1.创建一个新的promise对象
const p = new Promise((resolve, reject) => { //执行器函数是同步回调!
  console.log('执行 executor') //立刻执行
  //2.执行异步操作
  setTimeout(() => {  
    const time = Date.now()
    //3.1 成功,调用resolve(value)
    if( time % 2 === 0 ){
      resolve('成功的数据,time=' + time)
    } else {
    //3.2 失败,调用reject(reason)
      reject('失败的数据,time=' + time)
    }
  }, 1000)
})
console.log('new Promise()之后')  //先输出 '执行 exceutor'

p.then(
  value => { // onfulfilled函数,自动接收成功的value
    console.log('成功的回调', value)
  },
  reason => { // onrejected函数,自动接收失败的reason
    console.log('失败的回调', reason)
  }
)

API
在这里插入图片描述

new Promise( (resolve, reject) => {
  setTimeout( () => {
    resolve('成功') //resolve就像是一个传递数据的运输机
  }, 1000 )
}).then(
  value => {
    console.log('onResolved()1', value)
  }
).catch(
  reason => {
    console.log('onRejected()1', reason)
  }
)

const p1 = new Promise((resolve, reject) => {
  resolve(1)
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
// p1.then( value => {console.log(value)} )
// p2.then( value => {console.log(value)} )
// p3.catch( reason => {console.log(reason)} )

//const pAll = Promise.all([p1,p2,p3])
const pAll = Promise.all([p1,p2])
pAll.then(
  values => {
    console.log('all onResolved()', values)
  },
  reason => {
    console.log('all onRejected()', reason)
  }
)

const pRace = Promise.race([p1,p2,p3])
pRace.then(
  value => {
    console.log('race onResolved()', value)
  },
  reason => {
    console.log('race onResolved()', reason)
  }
)

一个promise指定多个成功/失败回调函数, 都会调用吗?
当promise改变为对应状态时都会调用

改变promise状态和指定回调函数谁先谁后?

  • 都有可能,正常情况下先指定回调在改变状态,也可以先改变状态在指定回调
  • 如何先改状态再指定回调?
    在执行器中直接调用resolve()/reject()
    延迟更长时间才调用then()
  • 什么时候才能得到数据?
    如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
    如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据

promise异常传透?
当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调(.catch()),前面任何操作出了异常, 都会传到最后失败的回调中处理。

中断promise链?
当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
办法: 在回调函数中返回一个pending状态的promise对象

promise和async|await的区别?

  • async / await 就是 Promise 的语法糖
  • promise错误可以通过catch来捕捉,建议尾部捕获错误, async/await既可以用.then又可以用try-catch捕捉

let 与 const

let、const、var的区别?

  • var是ES5提出的,let和const是ES6提出的
  • constlet 都是块级作用域,var 定义的变量为函数级作用域
  • const声明的是常量,必须赋值,不能使用null占位,声明后不能再修改,如果声明的是复合类型数据,可以修改其属性
  • var允许重复声明变量,后一个变量会覆盖前一个变量。let和const在同一作用域不允许重复声明变量
  • var声明的变量存在变量提升,值为undefinedlet和const不存在变量提升

ES7

数组.includes()

用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false

let arr = ['react', 'angular', 'vue']
//使用 includes() 验证数组中是否存在某个元素
if (arr.includes('react')) {
  console.log('react存在') //react存在
}
//使用 indexOf()验证数组中是否存在某个元素,需要根据返回值是否为 -1来判断
if (arr.indexOf('react') !== -1) {
  console.log('react存在') //react存在
}

ES8

async/await

await后面接一个会return new promise的函数并执行它
await只能放在async函数里
async函数会返回一个promise,并且Promise对象的状态值是resolved
await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。
用法:

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(m, n) {
    console.log(`step2 with ${m} and ${n}`);
    return takeLongTime(m + n);
}

function step3(k, m, n) {
    console.log(`step3 with ${k}, ${m} and ${n}`);
    return takeLongTime(k + m + n);
}
//使用async/await
async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time1, time2);
    const result = await step3(time1, time2, time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}
doIt();
// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 800 = 300 + 500
// step3 with 1800 = 300 + 500 + 1000
// result is 2000
// doIt: 2907.387ms

//使用promise
function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => {
            return step2(time1, time2)
                .then(time3 => [time1, time2, time3]);
        })
        .then(times => {
            const [time1, time2, time3] = times;
            return step3(time1, time2, time3);
        })
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}
doIt();

ES9

Object.values()

Object.values()是一个与 Object.keys()类似的新函数,但返回的是 Object 自身属性的所有值,不包括继承的值

const obj = { a: 1, b: 2, c: 3 }
//不使用 Object.values()
const vals = Object.keys(obj).map((key) => obj[key])
console.log(vals) //[1, 2, 3]

//使用 Object.values()
const values = Object.values(obj1)
console.log(values)//[1, 2, 3]

Object.entries()

Object.entries()函数返回一个给定对象自身可枚举属性的键值对的数组

//不使用Object.entries()
Object.keys(obj).forEach((key) => {
  console.log('key:' + key + ' value:' + obj[key])
})
//使用Object.entries()
for (let [key, value] of Object.entries(obj)) {
  console.log(`key: ${key} value:${value}`)
}
// key: a value:1
// key: b value:2
// key: c value:3

Rest/Spread 属性

为对象解构提供了和数组一样的 Rest 参数()和展开操作符,只适用于每个对象的顶层,如果对象中嵌套对象则无法适用

const myObject = {
  a: 1,
  b: 2,
  c: 3,
}
const { a, ...x } = myObject
// x = { b: 2, c: 3 }

ES10

Array的 flat()方法和 flatMap()方法

flat()和 flatMap()本质上就是是归纳(reduce) 与 合并(concat)的操作。

var arr1 = [1, 2, [3, 4, [5, 6]]]
arr1.flat() //[1, 2, 3, 4, [5, 6]]
arr1.flat(3) //[1, 2, 3, 4, 5, 6]

var arr4 = [1, 2, , 4, 5]
arr4.flat() //[1, 2, 4, 5]
var arr1 = [1, 2, 3, 4]
arr1.map((x) => [x * 2]) //[[2],[4],[6],[8]]
// 只会将 flatMap 中的函数返回的数组 “压平” 一层
arr1.flatMap((x) => [x * 2]) //[2,4,6,8]
arr1.flatMap((x) => [[x * 2]]) //[[2],[4],[6],[8]]

String的 trimStart()方法和 trimEnd()方法

分别去除字符串首尾空白字符

Object.fromEntries()

Object.fromEntries()Object.entries() 的反转
Object.fromEntries() 函数传入一个键值对的列表,并返回一个带有这些键值对的新对象。这个迭代参数应该是一个能够实现 @iterator 方法的的对象,返回一个迭代器对象。它生成一个具有两个元素的类似数组的对象,第一个元素是将用作属性键的值,第二个元素是与该属性键关联的值

//通过 Object.fromEntries, 可以将 Map 转化为 Object
const map = new Map([
  ['foo', 'bar'],
  ['baz', 42],
])
const obj = Object.fromEntries(map)
console.log(obj) //{foo: "bar", baz: 42}

//通过 Object.fromEntries, 可以将 Array 转化为 Object
const arr = [
  ['0', 'a'],
  ['1', 'b'],
  ['2', 'c'],
]
const obj = Object.fromEntries(arr)
console.log(obj) //{0: "a", 1: "b", 2: "c"}

新的基本数据类型 BigInt

JavaScript 中 Number 类型只能安全的表示-(2^53-1)至 2^53-1 范的值

var bigNumRet = 9007199254740993n + 9007199254740993n // -> -> 18014398509481986n
bigNumRet.toString() // -> '18014398509481986'

现在的基本数据类型加上BigInt一共有七种基本数据类型,分别是:String、Number、Boolean、Null、Undefined、Symbol、BigInt
注意: 尽可能避免通过调用函数 BigInt 方式来实例化超大整型。因为参数的字面量实际也是 Number 类型的一次实例化,超出安全范围的数字,可能会引起精度丢失

Symbol

symbol 是一种基本数据类型,表示独一无二的值。Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。
每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的

const symbol1 = Symbol();
const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');

console.log(typeof symbol1);  // "symbol"
console.log(symbol3.toString());  // "Symbol(foo)"
console.log(Symbol('foo') === Symbol('foo'));  // false

ES11

Promise.allSettled

我们需要一种机制,如果并发任务中,无论一个任务正常或者异常,都会返回对应的的状态(fulfilled 或者 rejected)与结果(业务 value 或者 拒因 reason),在 then 里面通过 filter 来过滤出想要的业务逻辑结果,这就能最大限度的保障业务当前状态的可访问性,而 Promise.allSettled 就是解决这问题的。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

Promise.allSettled(promises).
  then((results) => results.forEach((result) => console.log(result.status)));

// expected output:
// "fulfilled"
// "rejected"

Promise 中的三兄弟 .all(), .race(), .allSettled()

  • Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果
  • Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
  • Promise.allSettled()方法返回一个promise,该promise在所有给定的promise已被解析或被拒绝后解析,并且每个对象都描述每个promise的结果

可选链

可选链中的 ? 表示如果问号左边表达式有值, 就会继续查询问号后面的字段

//这是一种丑陋但又不得不做的前置校验,否则很容易命中 Uncaught TypeError: Cannot read property... 这种错误,这极有可能让你整个应用挂掉。
var age = user && user.info && user.info.getAge && user.info.getAge() 

//改写
var age = user?.info?.getAge?.()

空值合并运算符

当我们查询某个属性时,经常会遇到,如果没有该属性就会设置一个默认的值

var level = (user && user.level) || '暂无等级'
//在 JS 中,空字符串、0 等,当进行逻辑操作符判断时,会自动转化为 false,所以要用if去判断类型,
var level;
if (typeof user.level === 'number') {
    level = user.level;
} else if (!user.level) {
    level = '暂无等级';
} else {
    level = user.level;
}

//改写
var level = user.data?.level ?? '暂无等级' //暂无等级

dynamic-import

现代前端打包资源越来越大,打包成几 M 的 JS 资源已成常态,而往往前端应用初始化时根本不需要全量加载逻辑资源,为了首屏渲染速度更快,很多时候都是按需加载,比如懒加载图片等。而这些按需执行逻辑资源都体现在某一个事件回调中去加载

el.onclick = () => {
  import(`/path/current-logic.js`)
  .then((module) => {
  	module.doSomthing()
  }).catch((err) => {
    // load error;
  })
}

ES12

replaceAll

返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉

const str = 'hello world';
str.replaceAll('l', ''); // "heo word"

Promise.any

Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promiseAggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()是相反的。

const pErr = new Promise((resolve, reject) => {
  reject("总是失败");
});

const pSlow = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "最终完成");
});

const pFast = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "很快完成");
});

Promise.any([pErr, pSlow, pFast]).then((value) => {
  console.log(value);
  // pFast fulfils first
})
// 输出: "很快完成"

注: Promise.any() 方法依然是实验性的,尚未被所有的浏览器完全支持

逻辑运算符和赋值表达式

a ||= b
//等价于
a = a || (a = b)
 
a &&= b
//等价于
a = a && (a = b)
 
a ??= b
//等价于
a = a ?? (a = b)

数字分隔符

const money = 1_000_000_000;
//等价于
const money = 1000000000;
 
1_000_000_000 === 1000000000; // true

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值