【前端基礎系列】slice方法將類數組轉換數組實現原理
阿新 • • 發佈:2018-08-30
href ble 原理 prot creat urn dex 存在 返回
問題描述
在日常編碼中會遇到將類數組對象轉換為數組的問題,其中常用到的一種方式使用Array.prototype.slice()方法。
類數組對象
所謂的類數組對象,JavaScript對它們定義為:它們看起來很像數組,只是具有部分和數組相同特性:
- 擁有length屬性
- 元素保存在對象中,可以通過索引訪問
但是沒有數組的其他方法,例如:push、slice、indexOf等。
轉換過程
例如:
var foo = { 0: 'Java', 1: 'Python', 2: 'JavaScript', length: 3 }; // 因為foo對象本身並沒有slice方法,所以通過call調用 var arr = Array.prototype.slice.call(foo); // [‘Java’,’Python’,’JavaScript’]
那麽問題來了,為什麽slice方法可以將對象轉換為數組?最簡單的方式就是查看源碼實現。
源碼實現
可以查看V8引擎中的Array內部方法實現
function ArraySlice(start, end) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice"); var array = TO_OBJECT(this); var len = TO_LENGTH(array.length); var start_i = TO_INTEGER(start); var end_i = len; if (!IS_UNDEFINED(end)) end_i = TO_INTEGER(end); if (start_i < 0) { start_i += len; if (start_i < 0) start_i = 0; } else { if (start_i > len) start_i = len; } if (end_i < 0) { end_i += len; if (end_i < 0) end_i = 0; } else { if (end_i > len) end_i = len; } var result = ArraySpeciesCreate(array, MaxSimple(end_i - start_i, 0)); // 先轉換為數組 if (end_i < start_i) return result; // 如果沒有任何參數,直接返回數組 if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) { %NormalizeElements(array); if (IS_ARRAY(result)) %NormalizeElements(result); SparseSlice(array, start_i, end_i - start_i, len, result); } else { SimpleSlice(array, start_i, end_i - start_i, len, result); } result.length = end_i - start_i; return result; }
由以上代碼可以看出,當沒有輸入參數的時候,會創建一個新數組,然後把當前數組的所有元素扔進去,最後返回這個新數組。
參考
V8的array實現
【前端基礎系列】slice方法將類數組轉換數組實現原理