前端面試題整理—ES6篇

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

  ECMAScript5,即ES5,是ECMAScript的第五次修訂,於2009年完成標準化

  ECMAScript6,即ES6,是ECMAScript的第六次修訂,於2015年完成,也稱ES2015

  ES6是繼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)promise
  Promise是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理、強大

  13)Symbol
  Symbol是一種基本類型。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);
//1 2 4 3

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 = new Set();
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';
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章