博客 / 詳情

返回

深入一點 - JS 函數為什麼可以這樣操作

原文: https://zswfx.com/articles/5dc8f64a9cf7c17b240e5c6c

我們經常在函數參數裏面使用如下操作 Array.prototype.slice.call(arguments, 1), 這樣的操作,類似還有 Object.prototype.toString.apply(o)這種操作,為什麼可以這樣玩呢?

前言

我們經常通過數組的方法去操作類數組,還會使用一些JS對象的方法來獲取一個對象的真實的構造函數對象名稱。考慮類數組不是一個數組,是一個對象類似如下:

{
    "0": "b",
    "1": "a",
    "length": 2
}

這樣就可以使用,為什麼呢?

探索

為了搞清上面問題,我們就需要從兩個方面入手:

  • call/apply 定義
  • Array.prototype.slice、Object.prototype.toString

第一個需要找一下call/apply 調用流程,第二個看看規範如何定義這些方法

就已apply 為例(call類似), 具體方法以slice和toString為例

apply 規範

使用apply方法,有兩個作用

  • 1-8 處理通過 apply 方法傳入的參數
  • 9 處理改變函數的this值,並調用函數

上面調用函數,我們接下來就繼續看看函數如何處理

Array.prototype.slice

通過規範可以看出,Array也是通過key值獲取的,在第10步中可以看到循環獲取對象值,通過對象 [[Get]]的方式來獲取。

在每個數組方法後面,我們可以看到這樣一句話:

使用數組的所有方法,不一定要求對象是數組,只要符合能夠通過遞增的key值可以獲取的類數組對象即可使用.

下面繼續看看 toString

toString

我們正常使用 Object.prototype.toString.apply({}) 的結果是 [object Object]. 上面是規範結果

  • 第1步,確定 undefined 值為 [object Undefined]
  • 第2步,確定 null 值為 [object Null],
  • 第3步,通過內部方法 toObject 得到結果 (稍後説明toObject方法)
  • 第4步,獲取內部 [[Class]]
  • 第5步,拼接字符串 [object [[Class]], ] 返回結果

由此可得知,我們得到結果其實也是引擎根據規範來處理的。

toObject

toObject 的結果就是返回原始值(Primive Value)的盒裝對象(box model object).

最後 [[Class]]的獲取結果是一個説明對象分類名稱的字符串。

最後

最近探索規範,發現越來越多想法和只是和規範一一驗證。探索規範過程也是一種進步過程,任何小的改變,都是有跡可循,任何東西都來自規範。正如有理論支持的代碼,才是堅不可摧,否則就如同一盤散沙。

歡迎交流.
user avatar yiiouo 頭像 william_wang_5f4c69a02c77b 頭像 clearlove07 頭像 shen_5bbe318c912ed 頭像 bupthly 頭像 ran_agppr 頭像 yxaw 頭像 yzsunlei 頭像 yangzw 頭像 mall4j 頭像 dexteryao 頭像
11 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.