解決方法

仔細再看一下到底你是如何調用apply的。。。

你可能在使用Function.prototype.apply的時候不夠熟練,把callapply的用法混在一起。。。。call是用0個或者更多的arguments,而apply則是用一個數組。

錯誤例子

Math.max.apply(null, 1, 2, 3);
// Uncaught TypeError: CreateListFromArrayLike called on non-object

正確例子

Math.max.call(null, 1, 2, 3); // 3
Math.max.apply(null, [1, 2, 5, 10]); // 10

細節

當調用Function.prototype.apply的時候,它會調用內置抽象操作:CreateListFromArrayLike

CreateListFromArrayLike

CreateListFromArrayLike ( obj [ , elementTypes ] )

CreateListFromArrayLike 是一個ECMAScript的內置抽象操作 (Abstract Operation),用於建立一個List的值,它的元素由類似數組的對象的索引屬性提供。elementTypes是一個List,只允許自身建立的list擁有ECMAScript Language 類型的值,比如undefined, null, boolean等。在調用的時候,它會執行以下步驟:

  1. 如果沒有定義elementTypes的話,它會被定義為« Undefined, Null, Boolean, String, Symbol, Number, Object »。
  2. 如果Type(obj)的類型不是Object,拋出TypeError 錯誤。
  3. 定義lenobj的length。
  4. 建立一個空的List list
  5. 定義index為0
  6. 當index小於len的時候,重複以下步驟:
    1. 定義indexName為!ToString(index)
    2. 定義next 為?Get(obj, indexName)
    3. 如果Type(next)的類型不存在於elementType裡面,拋出TypeError 錯誤。
    4. list的最後增加next //list.push(next)
    5. index的值加1
  7. 返回list

延伸閱讀

  1. 看V8是怎樣實現Function.prototype.apply
  2. 看V8是怎樣實現CreateListFromArrayLike

參考資料

  1. Function.prototype.apply - ECMAScript 2018
  2. 踩過的坑。。。
如果你覺得我的文章對你有幫助的話,希望可以推薦和交流一下。歡迎關注和 Star 本博客或者關注我的 Github