經典大廠前端面試題(含解析)基礎篇(一)

年關將近,金三銀四跳槽季要來了,開始整理面試題前端

基礎類型有哪些?

基本類型有七種面試

  1. null
  2. undefined
  3. boolean
  4. number
  5. string
  6. symbol(較新標準)
  7. BigInt(新標準)

NaN 也屬於 number 類型,而且 NaN 不等於自身數組

基礎類型的特性是什麼?

  1. 基本類型的值是保存在棧內存中的簡單數據段
  2. 基礎類型是不可變的
    • 即不能強行修改:Array.prototype.sort.call('abc');(會報錯)
  3. 基礎類型上沒有__proto__沒有屬性
  4. 基礎類型能夠經過 基本包裝類型 訪問的屬性/方法
    // 經過包裝類型訪問基礎類型特性
        let str = 'abc';
        console.log(str.length)
    
        // 當你調用 `str.length` 時,實際過程是這樣的:
        // -> 建立String類型的一個實例
        // -> 在實例上調用指定的方法
        // -> 銷燬這個實例
    
        let _str = new String(str);
        let len = _str.length;
        _str = null;
    複製代碼

怎麼檢測基礎類型?

  1. 檢測基礎類型能夠用 typeof,可是 typeof null === 'object'
    • null 是基礎類型,不是 Object
    • 因爲null的歷史遺留問題(前三位爲000),因此使用typeof檢測null會產生BUG
    // 借鑑 Vue 源碼的 object 檢測方法
        function isObject (obj: any): Boolean {
            return obj !== null && typeof obj === 'object'
        }
    複製代碼
  2. 經過 Object.prototype.toString.call (萬能方法)
    • 檢測 [[class]]
    • 在不覆蓋 toString 方法前提下,任何一個對象調用 Object 原生的 toString 方法都會返回 [object type]
    // 借鑑 Vue 源碼的檢測方法
    
        let _toString = Object.prototype.toString;
    
        function toRawType (value: any): String {
            // 獲取 從第九個到倒數第二個 字符
            // 好比 [object String]  獲取 String
            return _toString.call(value).slice(8, -1)
        }
    複製代碼

基礎類型是如何轉換的?

  1. 基本類型轉換時,首先會調用 valueOf,而後調用 toString。(這兩個方法能夠被重寫)
  2. 在四則運算中,除了 + 其餘操做都會以數字進行計算,若是是 + 運算,若是不是全部字面量都是number(都是number就是數字的加法咯),那麼會轉換爲字符串(toString)進行拼接

爲何 0.1 + 0.2 爲何不等於 0.3 ?

遵循IEEE 754 雙精度版本(64位)標準的語言都有的問題。計算機沒法識別十進制,JS會將十進制轉換爲對應的二進制(二進制即:01)。bash

那麼 怎麼用 01 來表示 0.10.2 呢?微信

console.log(0.1.toString(2));
    // -> 0.0001100110011001100110011001100110011001100110011001101

    console.log(0.2.toString(2));
    // -> 0.001100110011001100110011001100110011001100110011001101
複製代碼

這樣看似沒問題啊。爲何會有BUG呢?函數

別忘了:JS的精確度區間 約爲正負 2^53,超出限制會截斷。因此你看到的 0.1 不是真的 0.1。ui

那麼怎麼解決 JS 的精確度問題?

  1. 目前主流的解決方案是 先乘再除
    • 好比精確到小數點後2位
    • 先把須要計算的數字都 乘1000
    • 計算完成後再把結果 除1000
  2. 使用新基礎類型 BigInt (兼容性不好)

JS的"真"值有哪些?

JS中除了 "假" 值之外就是 "真" 值。this

"假"值包括 7 個spa

  1. undefined
  2. null
  3. false
  4. NaN
  5. ''
  6. 0
  7. -0

在條件判斷的隱式轉換中:"假" 值會轉換爲 false,"真" 值會轉換爲 true;prototype

那說一下引用類型吧?

  1. 除了基礎類型,都是引用類型。
  2. 引用類型正在建立時會分配兩個空間
    • 一塊在上,儲存引用類型自己的數據(固然數據量會比較大)
    • 一塊在上,儲存對上數據的引用(存儲堆上的內存地址,也就是指針)
  3. 引用類型是可變的:即let a={}; a.x=1;
  4. function參數是值傳遞,要注意不能修改引用

怎麼檢測引用類型?

  1. 經過 Object.prototype.toString.call 檢測 [[class]]
  2. 經過 instanceof 判斷引用類型
  3. 經過 constructor 判斷引用類型(constructor是可寫的,慎用)

instanceof 的原理是什麼?

instanceof 內部機制是經過判斷對象的原型鏈中是否是能找到對應的的prototype

因此在驗證iframe時會有BUG,由於 window.Array.prototype !== window.frames[0].Array.prototype,因此不存在繼承關係

// 實現 instanceof

  function instanceof(obj, target) {
      // 得到對象的原型
      obj = obj.__proto__
      // 判斷對象的類型是否等於類型的原型
      while (true) {
        // 若是__proto__ === null 說明原型鏈遍歷完畢
        if (obj === null) {
          return false
        }
        // 若是存在 obj.__proto__ === target.prototype
        // 說明對象是該類型的實例
        if (obj === target.prototype) {
          return true
        }
        // 原型鏈上查找
        obj = obj.__proto__
      }
  }
複製代碼

若是用 instanceof 判斷基礎類型會怎麼樣?

會返回 false 由於基礎類型沒有 __proto__

let str = '123';

    console.log(str instanceof String) // -> false
複製代碼

可是若是更改了 靜態方法Symbol.hasInstance就能夠判斷了

class StringType {
        static [Symbol.hasInstance](val) {
            return typeof val === 'string'
        }
    }
    console.log(str instanceof StringType) // -> true
複製代碼

說一下數組吧?

數組是一種類列表對象,其數據在內存中也能夠不連續

數組應該是一段線性分配的內存,可是JS的Array的檢索和更新方式和對象如出一轍

  • Array它把下標變成數字,用其做屬性。它比真正的數組慢,但用起來更方便。
  • Array本質仍是對象,其原型繼承自Array.prototype,向上再繼承自Object.prototype
  • Array的方法是設計爲對象通用的,對象也能調用數組的方法
    let obj = {
            '2': 3,
            '3': 4,
            'length': 2,
            'splice': Array.prototype.splice,
            'push': Array.prototype.push
        }
        obj.push(1)
        obj.push(2)
    
        console.log(obj);
        // Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]
    複製代碼
  • 使用delete arr[2],並不能減小length,而只是刪除了對應的屬性(變成empty)

什麼是類數組?

  1. 類數組不是數組,經過 Array.isArray() 會返回 false
  2. 類數組經過 Array.from 能夠轉換爲數組
  3. 屬性要爲索引(數字)屬性
  4. 必須有length屬性

常常碰見的類數組

  • 字符串
    • 惟一的原生類數組
  • arguments
    • arguments徹底可使用...args代替,這樣不定參數就是真數組
    • arguments在箭頭函數中被移除
  • DOM

[] == ![] 結果是什麼?

PS: 感謝 @沉末_ 的補充

類型轉換都是先 valueOftoString;

右邊

  1. 因爲 ! 優先級比 == 高,先執行 !
  2. ![] 獲得 false
  3. 進行 相等性判斷
  4. false 轉化爲數字 0

左邊

  1. 執行 [].valueOf() 原始值 仍是 []
  2. 執行 [].toString() 獲得 ''
  3. '' 轉化爲數字 0

因此:0 == 0 ,答案是 true

驗證:

let arr1 = [];
    let arr2 = [];

    console.log(arr1 == !arr2) // -> true

    arr1.toString = () => {
        console.log(111)
        return 1
    }

    console.log(arr1 == !arr2) 
    // -> 111
    // -> false
複製代碼

== 和 === 的區別 ?

  1. === 不進行隱式轉換
  2. == 會進行隱式轉換
    • {a: 1} == "[object Object]" 左邊會執行 .toString()

如何讓 (a == 1 && a == 2)條件成立?

依然是類型轉換邏輯:基礎類型經過 valueOf 進行隱式轉換

更改 valueOf 方法就能夠實現

let a = {
        value: 0,
        valueOf: function() {
            this.value++;
            return this.value;
        }
    };
    console.log(a == 1 && a == 2);
複製代碼

Object.is 和 === 的區別 ?

Object.is(v1, v2) 修復了 === 的一些BUG (-0和+0, NaN和NaN)

// === 案例
    -0 === +0       // -> true
    NaN !== NaN     // -> false

    Object.is(-0, +0)       // -> false
    Object.is(NaN, NaN)     // -> true
複製代碼

關注微信號"前端進階課" 回覆"Vue"、"React"、"KOA"、"全棧" 有相關課程贈送哦。文章將不按期發送閱讀紅包,敬請期待

相關文章
相關標籤/搜索