學習-ES6基礎知識點

前言

本篇文章介紹面試中常常問的ES6基礎知識點。文章中的關聯問題能夠在面試官問了問題後本身進行引伸這些相關話題,從而引導面試官詢問本身擅長的部分。後續會持續推出HTML知識點、CSS知識點、JS進階知識點、webpack知識點、react知識點、組件設計相關知識點、瀏覽器相關知識點、網絡相關知識點、算法相關知識點等文章進行全面的知識梳理。javascript

塊級做用域

Q: 如何理解let和const,和var有什麼區別?
A: let 和 const 沒有變量提高、不能重複聲明、不綁定全局做用域。
關聯Q: 如何理解臨時性死區?
關聯A: JavaScript 引擎會掃描變量聲明,會放入臨時死區,若是發現若是在聲明變量以前訪問這些變量,會致使報錯。
關聯Q: 有沒有研究過babel是怎麼編譯let的?
關聯A: 若是有兩個同樣的變量名,會編譯成不一樣的變量名,若是是循環中的申明,它會編譯成兩個方法,進行循環調用傳入參數的方法。
java

箭頭函數

Q: 箭頭函數有什麼特性?
A: 沒有 this、沒有 arguments、不能用 new 關鍵字調用、沒有new.target、沒有原型、沒有 super。
關聯Q: 如何肯定箭頭函數的this?
關聯A: 經過查找做用域鏈來肯定 this,也就是最近一層非箭頭函數的this。
react

Symbol類型

Q: Symbol 有哪些特性?
A: Symbol的值表示獨一無二的值、typeof 類型是 Symbol、不能使用 new 命令、Symbol 一個對象,調用的是對象的toString()、相同參數的 Symbol 函數返回值不相等、Symbol值不能與其餘類型進行運算、Symbol 能夠用於對象的屬性名
關聯Q: 爲何不能使用new命令?
關聯A: 由於 Symbol 是原始類型,不是對象。
關聯Q: 能夠用forin或者forof獲取屬性名嗎?
關聯A: 只能用Object.getOwnPropertySymbols獲取屬性名
webpack

迭代器與forof

Q: 什麼是迭代器?
A: 迭代器就是一個擁有 next 方法的對象,每次調用next()會返回一個 value 和 done 屬性的結果對象。
關聯Q: forof能夠遍歷哪些對象,能夠直接遍歷一個普通對象嗎?
關聯A: 數組、Set、Map、類數組對象、Generator 對象、字符串,forof能夠遍歷的本質是對象中有 Symbol.iterator 屬性。
es6

Promise

Q: 如何理解Promise?
A: 優勢:鏈式調用,解決回調的控制反轉和回調地獄的問題,缺點: 沒法取消 Promise,沒法得知 pending 狀態
關聯Q: Promise內部實現?
關聯A: 通常會讓你手寫 Promise 的 某一個函數,能夠本身去實現一下整個 Promise,在文章最後有簡單實現的代碼。
web

class

Q: 分別用es5和es6的方式實現繼承?
A: es6 比較簡單,直接用 extends 實現。es5 比較典型的實現方式就是寄生組合繼承,核心思想就是將父類的原型賦值給子類,而且將構造函數設置爲子類。在文章最後有簡單實現的代碼。
面試

模塊化

Q: 模塊化有什麼好處?爲何使用模塊化?
A: 解決命名衝突、提供複用性、提升代碼可維護性。
關聯Q: 如何實現模塊化?
關聯A: 可使用當即執行函數實現模塊化。
關聯Q: CommonJS和es Module有哪些區別?
關聯A: CommonJS 是同步導入,用於服務端;ES module 是異步導入,用於瀏覽器; CommonJS 輸出的是對於值的拷貝,ES module 輸出的是對值的引用;CommonJS 模塊是運行時加載,ES module 模塊是編譯時輸出接口
算法

Promise 源碼實現

const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

function MyPromise(fn) {
  this.state = PENDING
  this.value = null
  this.resolvedCallbacks = []
  this.rejectedCallbacks = []

  function resolve(value) {
    if (this.state === PENDING) {
      this.state = RESOLVED
      this.value = value
      this.resolvedCallbacks.forEach(cb => cb(value))
    }
  }

  function reject(value) {
    if (this.state === PENDING) {
      this.state = REJECTED
      this.value = value
      this.rejectedCallbacks.forEach(cb => cb(value))
    }
  }

  try {
    fn(resolve, reject)
  } catch (e) {
    reject(e)
  }
}

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
  onRejected = typeof onRejected === 'function' ? onRejected : e => {throw e}
  const that = this
  let promise2 = new Promise((resolve, reject) => {
    if (that.state === PENDING) {
      that.resolvedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onFulfilled(that.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      })
      that.rejectedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onRejected(that.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      })
    }
    if (this.state === RESOLVED) {
      setTimeout(() => {
        try {
          const x = onFulfilled(this.value)
          resolvePromise(promise2, x, resolve, reject)
        } catch(e) {
          reject(e)
        }
      })
    }
    if (this.state === REJECTED) {
      setTimeout(() => {
        try {
          const x = onRejected(this.value)
          resolvePromise(promise2, x, resolve, reject)
        } catch(e) {
          reject(e)
        }
      })
      
    }
  })
  return promise2
}

function resolvePromise(promise2, x, resolve, reject) {
  if(promise2 === x) {
    reject(new TypeError('Error'))
  }
  if (x && typeof x === 'object' || typeof x === 'function') {
    let called;
    try {
      let then = x.then
      if (typeof then === 'function') {
        then.call(x, y => {
          if (called) return
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, e => {
          if (called) return
          called = true
          reject(e)
        })
      } else {
        if (called) return
        called = true
        resolve(x)
      }
    } catch(e) {
      if (called) return
      called = true
      reject(e)
    }
  } else {
    resolve(x)
  }
}

MyPromise.prototype.catch = function(onRejected) {
  return this.then(null, onRejected)
}

MyPromise.prototype.finally = function(callback) {
  return this.then(value => {
    return Promise.resolve(callback()).then(() => value)
  }, err => {
    return Promise.resolve(callbakck()).then(() => {throw err})
  })
}

MyPromise.all = function(promises) {
  return new Promise((resolve, reject) => {
    let index = 0
    let result = []
    if (promises.length === 0) {
      resolve(result)
    } else {
      for(let i = 0; i < promises.length; i++) {
        Promise.resolve(promises[i]).then(data => {
          result[i] = data
          if (++index === promises.length) resolve(result)
        }, err => {
          reject(err)
          return
        })
      }
    }
  })
}

MyPromise.race = function(promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      return
    } else {
      for(let i = 0; i < promises.length; i++) {
        Promise.resolve(promises[i]).then(data => {
          resolve(data)
          return
        }, err => {
          reject(err)
          return
        })
      }
    }
  })
}
複製代碼

寄生組合繼承

function Parent(value) {
    this.val = value
  }
  Parent.prototype.getValue = function() {
    console.log(this.val)
  }
  function Child(value) {
    Parent.call(this, value)
  }
  Child.prototype = Object.create(Parent.prototype)
  Child.prototype.constructor = Child
  
  const child = new Child(1)

複製代碼
相關文章
相關標籤/搜索