1. 程式人生 > >【前端基礎系列】slice方法將類數組轉換數組實現原理

【前端基礎系列】slice方法將類數組轉換數組實現原理

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方法將類數組轉換數組實現原理