前端小生面試之看不懂的 []+{}

面試滑鐵盧

有一天,去面試,遇到這樣的題:html

[]+[]
{}+{}
1+[]
複製代碼

???WTF,誰會沒事這麼寫代碼,好吧,我錯了,大佬別打我。懵逼以後要幹嗎?固然是要學習一波,因而我滿世界找資料,有好東西固然是要分享一波,好了,接下來咱們就一塊兒走進 JavaScript 隱式轉換的世界吧。git

加法運算

在 JavaScript 中加法運算規則很簡單,它只作數字和字符串的加法操做,全部不是這兩種類型的都會被轉換成這兩種原始數據類型再進行操做。github

在 JavaScript 中,數據類型分兩種:面試

  • 原始數據類型(primitives): undefined, null, boolean, number,string,symbol
  • 其餘的都是對象,包括數組、函數。

那麼對象是如何轉換成原始數據類型的呢?不要慌,咱們繼續看。數組

ToPrimitive

JS 有一個內部運算 ToPrimitive(),它用於對象轉換爲原始數據類型。瀏覽器

ToPrimitive(input, PreferredType?)
複製代碼

這個函數接收兩個參數:函數

  • input: 這個參數是輸入的值。
  • PreferredType: 這個參數能夠Number 或者是 String,這表明了咱們的對象優先會轉換成哪一種原始數據類型。若是缺乏這個參數的話,那對於 Date 的實例,默認爲 String,其他的都爲 Number。轉換的步驟也會由於這個參數而有所不一樣。

下面咱們來看一下對於不一樣的參數,它的轉換過程是什麼樣的?學習

PreferredType 爲 Number

  1. 若是 input 爲原始類型,則直接返回 input。
  2. 不然,若是 input 是一個對象,則會去調用對象的 valueOf() 方法,若是結果爲原始類型就直接返回。
  3. 若是上一步返回的依然是對象,那麼就回去調用對象的 toString() 方法,若是結果爲原始數據類型就返回。
  4. 若是還不是原始數據類型就拋出錯誤,通常是 Uncaught TypeError: Cannot convert object to primitive value

PreferredType 爲 String

參數 String 就不細說了,當參數爲 String 的時候,上面的第二步和第三步交換就好了,也就是先調用 toString() 再調用 valueOf()測試

+ 運算

value1 + value2
複製代碼

上面的操做方式以下:ui

  1. 將兩個操做數轉換成基本數據類型:
 // PreferredType被省略,所以非日期爲 Number,日期爲 String。
prim1 = ToPrimitive(value1)
prim2 = ToPrimitive(value2)
複製代碼
  1. 若是 prim1 或 prim2 是一個字符串,則將其轉換爲字符串並返回結果的鏈接。
  2. 不然,將 prim1 和 prim2 都轉換爲數字並返回結果的總和。

valueOf 和 toString

這兩個都是 Object 的屬性,能夠本身定義,如今咱們無論,咱們去看看下面幾種狀況這兩個方法返回的都是什麼。

// 對象
const a1 = {
  a: 1
};
console.log(a1.valueOf());
console.log(a1.toString());
// 數組
const a2 = [1,2,3];
console.log(a2.valueOf());
console.log(a2.toString());
// 方法
const a3 = function() {
  const a = 1;
  return 1;
};
console.log(a3.valueOf());
console.log(a3.toString());
複製代碼

將上面的代碼放到控制檯打印一下就知道:

  • 對象: valueOf() 返回對象自己,toString() 返回值爲 [object Object]。
  • 數組: valueOf() 返回對象自己,數組改寫了 toString(),返回值至關於用 join(',') 的返回值,好比 [1,2,3].toString() 返回 "1,2,3"。
  • 方法: valueOf() 返回方法自己,Function 也改寫了對象的 toString(),它將代碼轉爲字符串值而後返回。

舉個栗子

好了,根據咱們上面說的,那些面試題簡直灑灑水,咱們來看。

[]+{}
複製代碼

咱們如何去分析呢?在這裏,咱們首先將 [] 和 {} 轉換成原始數據類型,也就是 ToPrimitive([]) 以及 ToPrimitive({}),PreferredType 默認爲 Number,很明顯 [].valueOf() 仍是一個對象,因此咱們繼續,[].toString() 結果爲 "",相同的解析過程 {} 轉換成 "[object Object]"。

好了,如今這個式子是 "" + "[object Object]",咱們知道 + 運算只要有字符串就拼接操做數,因此結果是 "[object Object]"。

可是,在我進行測試的時候,發現了幾個特殊的例子,{}+1{}+[] 這兩個例子在控制檯打印出的結果爲 1"",很奇怪是吧?我搜了搜資料發現,不一樣瀏覽器對其的解析不一樣,它會將前面一個 {} 當成代碼塊,因而上面的式子就變成了 +1+[],因此得出了上面的結果。

總結

好了,通過上面的探究,我相信你們不會再被這些問題難住了,可是要記住,{} 在前面的狀況下可能會由於瀏覽器的差別會形成不一樣的結果,固然,若是你這樣將 {} 用 () 包起來就不會有問題了,或者是先聲明在使用。

更多資源

更多文章盡在 個人博客倉庫,若是各位讀者以爲有用,歡迎 star,不勝感激。

相關文章
相關標籤/搜索