ES6常見面試題總結

前端一枚發表於2020-12-30

1、es5和es6的區別,說一下你所知道的es6

ECMAScript5,即ES5,是ECMAScript的第五次修訂,於2009年完成標準化ECMAScript6,即ES6,是ECMAScript的第六次修訂,於2015年完成,也稱ES2015ES6是繼ES5之後的一次改進,相對於ES5更加簡潔,提高了開發效率ES6新增的一些特性:
1)let宣告變數和const宣告常量,兩個都有塊級作用域ES5中是沒有塊級作用域的,並且var有變數提升,在let中,使用的變數一定要進行宣告
2)箭頭函式ES6中的函式定義不再使用關鍵字function(),而是利用了()=>來進行定義
3)模板字串模板字串是增強版的字串,用反引號(`)標識,可以當作普通字串使用,也可以用來定義多行字串
4)解構賦值ES6 允許按照一定模式,從陣列和物件中提取值,對變數進行賦值
5)for of迴圈for...of迴圈可以遍歷陣列、Set和Map結構、某些類似陣列的物件、物件,以及字串
6)import、export匯入匯出ES6標準中,Js原生支援模組(module)。將JS程式碼分割成不同功能的小塊進行模組化,將不同功能的程式碼分別寫在不同檔案中,各模組只需匯出公共介面部分,然後通過模組的匯入的方式可以在其他地方使用
7)set資料結構Set資料結構,類似陣列。所有的資料都是唯一的,沒有重複的值。它本身是一個建構函式
8)... 展開運算子可以將陣列或物件裡面的值展開;還可以將多個值收集為一個變數
9)修飾器 @decorator是一個函式,用來修改類甚至於是方法的行為。修飾器本質就是編譯時執行的函式
10)class 類的繼承ES6中不再像ES5一樣使用原型鏈實現繼承,而是引入Class這個概念11)async、await使用 async/await, 搭配promise,可以通過編寫形似同步的程式碼來處理非同步流程, 提高程式碼的簡潔性和可讀性async 用於申明一個 function 是非同步的,而 await 用於等待一個非同步方法執行完成
12)promisePromise是非同步程式設計的一種解決方案,比傳統的解決方案(回撥函式和事件)更合理、強大
13)SymbolSymbol是一種基本型別。Symbol 通過呼叫symbol函式產生,它接收一個可選的名字引數,該函式返回的symbol是唯一的
14)Proxy代理使用代理(Proxy)監聽物件的操作,然後可以做一些相應事情

2、var、let、const之間的區別

var宣告變數可以重複宣告,而let不可以重複宣告
var是不受限於塊級的,而let是受限於塊級
var會與window相對映(會掛一個屬性),而let不與window相對映
var可以在宣告的上面訪問變數,而let有暫存死區,在宣告的上面訪問變數會報錯
const宣告之後必須賦值,否則會報錯
const定義不可變的量,改變了就會報錯
const和let一樣不會與window相對映、支援塊級作用域、在宣告的上面訪問變數會報錯

3、使用箭頭函式應注意什麼?

(1)用了箭頭函式,this就不是指向window,而是父級(指向是可變的)
(2)不能夠使用arguments物件
(3)不能用作建構函式,這就是說不能夠使用new命令,否則會丟擲一個錯誤
(4)不可以使用yield命令,因此箭頭函式不能用作 Generator 函式

4、ES6的模板字串有哪些新特性?並實現一個類别範本字串的功能

基本的字串格式化。
將表示式嵌入字串中進行拼接。
用${}來界定在ES5時我們通過反斜槓()來做多行字串或者字串一行行拼接。
ES6反引號(``)就能解決類别範本字串的功能
let name = 'web';
let age = 10;
let str = '你好,${name} 已經 ${age}歲了'
str = str.replace(/\$\{([^}]*)\}/g,function(){
     return eval(arguments[1]);
   })
console.log(str);//你好,web 已經 10歲了

5、介紹下 Set、Map的區別?

應用場景Set用於資料重組,Map用於資料儲存Set: 
(1)成員不能重複
(2)只有鍵值沒有鍵名,類似陣列
(3)可以遍歷,方法有add, delete,has
Map:
(1)本質上是健值對的集合,類似集合
(2)可以遍歷,可以跟各種資料格式轉換

6、ECMAScript 6 怎麼寫 class ,為何會出現 class?

ES6的class可以看作是一個語法糖,它的絕大部分功能ES5都可以做到,新的class寫法只是讓物件原型的寫法更加清晰、更像物件導向程式設計的語法
//定義類
class Point { 
  constructor(x,y) { 
      //構造方法
       this.x = x; //this關鍵字代表例項物件
       this.y = y; 
  } toString() {
       return '(' + this.x + ',' + this.y + ')'; 
  }
}

7、Promise建構函式是同步執行還是非同步執行,那麼 then 方法呢?

promise建構函式是同步執行的,then方法是非同步執行的

8、setTimeout、Promise、Async/Await 的區別

事件迴圈中分為巨集任務佇列和微任務佇列
其中setTimeout的回撥函式放到巨集任務佇列裡,等到執行棧清空以後執行promise.then裡的回撥函式會放到相應巨集任務的微任務佇列裡,等巨集任務裡面的同步程式碼執行完再執行async函式表示函式裡面可能會有非同步方法,await後面跟一個表示式
async方法執行時,遇到await會立即執行表示式,然後把表示式後面的程式碼放到微任務佇列裡,讓出執行棧讓同步程式碼先執行

9、promise有幾種狀態,什麼時候會進入catch?

三個狀態:
pending、fulfilled、reject
兩個過程:
padding -> fulfilled、padding -> rejected當pending為rejectd時,會進入catch

10、下面的輸出結果是多少

const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
})


promise.then(() => {
    console.log(3);
})


console.log(4);
Promise 新建後立即執行,所以會先輸出 1,2,而 Promise.then()內部的程式碼在 當次 事件迴圈的 結尾 立刻執行 ,所以會繼續輸出4,最後輸出3

11、使用結構賦值,實現兩個變數的值的交換

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

12、設計一個物件,鍵名的型別至少包含一個symbol型別,並且實現遍歷所有key

let name = Symbol('name');
 let product = {
    [name]:"洗衣機",    
    "price":799
  };
  Reflect.ownKeys(product);

13、下面Set結構,列印出的size值是多少

let s = newSet();
s.add([1]);s.add([1]);
console.log(s.size);
答案:2
兩個陣列[1]並不是同一個值,它們分別定義的陣列,在記憶體中分別對應著不同的儲存地址,因此並不是相同的值都能儲存到Set結構中,所以size為2

14、Promise 中reject 和 catch 處理上有什麼區別

reject 是用來丟擲異常,catch 是用來處理異常
reject 是 Promise 的方法,而 catch 是 Promise 例項的方法
reject後的東西,一定會進入then中的第二個回撥,如果then中沒有寫第二個回撥,則進入catch
網路異常(比如斷網),會直接進入catch而不會進入then的第二個回撥

15、使用class 手寫一個promise

//建立一個Promise的類
  class Promise{
    constructor(executer){//建構函式constructor裡面是個執行器
      this.status = 'pending';//預設的狀態 pending
      this.value = undefined//成功的值預設undefined
      this.reason = undefined//失敗的值預設undefined
      //狀態只有在pending時候才能改變
      let resolveFn = value =>{
        //判斷只有等待時才能resolve成功
        if(this.status == pending){
          this.status = 'resolve';
          this.value = value;
        }
      }
      //判斷只有等待時才能reject失敗
      let rejectFn = reason =>{
        if(this.status == pending){
          this.status = 'reject';
          this.reason = reason;
        }
      }    
      try{
        //把resolve和reject兩個函式傳給執行器executer
        executer(resolve,reject);
      }catch(e){
        reject(e);//失敗的話進catch
      }
    }
    then(onFufilled,onReject){
      //如果狀態成功呼叫onFufilled
      if(this.status = 'resolve'){
        onFufilled(this.value);
      }
      //如果狀態失敗呼叫onReject
      if(this.status = 'reject'){
        onReject(this.reason);
      }
    }
  }

16、如何使用Set去重

let arr = [12,43,23,43,68,12];
let item = [...new Set(arr)];
console.log(item);//[12, 43, 23, 68]

17、將下面for迴圈改成for of形式

let arr = [11,22,33,44,55];
let sum = 0;
for(let i=0;i<arr.length;i++){
    sum += arr[i];
}
答案:
let arr = [11,22,33,44,55];
let sum = 0;
for(value of arr){
    sum += value;
}

18、理解 async/await以及對Generator的優勢

async await 是用來解決非同步的,async函式是Generator函式的語法糖
使用關鍵字async來表示,在函式內部使用 await 來表示非同步
async函式返回一個 Promise 物件,可以使用then方法新增回撥函式
當函式執行的時候,一旦遇到await就會先返回,等到非同步操作完成,再接著執行函式體內後面的語句
async較Generator的優勢:
(1)內建執行器。Generator 函式的執行必須依靠執行器,而 Aysnc 函式自帶執行器,呼叫方式跟普通函式的呼叫一樣
(2)更好的語義。async 和 await 相較於 * 和 yield 更加語義化  
(3)更廣的適用性。yield命令後面只能是 Thunk 函式或 Promise物件,async函式的await後面可以是Promise也可以是原始型別的值
(4)返回值是 Promise。async 函式返回的是 Promise 物件,比Generator函式返回的Iterator物件方便,可以直接使用 then() 方法進行呼叫

19、forEach、for in、for of三者區別

forEach更多的用來遍歷陣列
for in 一般常用來遍歷物件或json
for of陣列物件都可以遍歷,遍歷物件需要通過和Object.keys()
for in迴圈出的是key,for of迴圈出的是value

20、說一下es6的匯入匯出模組

匯入通過import關鍵字
// 只匯入一個
import {sum} from "./example.js"
// 匯入多個
import {sum,multiply,time} from "./exportExample.js"
// 匯入一整個模組
import * as example from "./exportExample.js"
匯出通過export關鍵字
//可以將export放在任何變數,函式或類宣告的前面
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//也可以使用大括號指定所要輸出的一組變數
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
//使用export default時,對應的import語句不需要使用大括號
let bosh = function crs(){}
export default bosh;
import crc from 'crc';
//不使用export default時,對應的import語句需要使用大括號
let bosh = function crs(){}
export bosh;
import {crc} from 'crc';

相關文章