ECMAScript 的 Array.prototype
亦提供 slice()
取得部分 Array,也可套用在 Array-like object。
Imperative
let data = [1, 2, 3, 4, 5]
let slice = begin => end => arr => {
let result = []
for(let i = 0; i < arr.length; i++)
if (i >= begin && i < end)
result.push(arr[i])
return result
};
slice(1)(3)(data) // ?
Imperative 會先建立欲回傳的 result
array,使用 for
loop 搭配 if
判斷,若 index
在傳進的 begin
與 end
之中,則塞進 result
中。
slice()
let data = [1, 2, 3, 4, 5]
data.slice(1, 3) // ?
ECMAScript 原生的 Array.prototype
已內建 slice()
,可直接使用。
arr.slice([begin[, end]])
取得部分 array
begin
:array 的起始 index
end
:array 的結束 index (但不包含)
let data = [1, 2, 3, 4, 5]
data.slice(1, -2) // ?
Index 也可以傳入負數,其中 -1
就是最後一個 element,-2
就是倒數第二個 element,以此類推。
let data = [1, 2, 3, 4, 5]
data.slice() // ?
若 slice()
不提供任何 argument,則相當於 shallow copy 完整 array。
Array-like object
let fn = function() {
return Array.prototype.slice.call(arguments, 1, 3)
}
fn(1, 2, 3, 4, 5) // ?
透過 Array.prototype.slice().call()
,slice()
也可套用在 array-like object。
只有 function declaration 與 function expression 可用
arguments
,arrow function 不行
let fn = function() {
return [].slice.call(arguments, 1, 3)
}
fn(1, 2, 3, 4, 5) // ?
[]
的 slice()
繼承自 Array.prototype
,故也可用 [].slice()
取代之。
let _slice = Array.prototype.slice
let slice = Function.prototype.call.bind(_slice)
let fn = function() {
return slice(arguments, 1, 3)
}
fn(1, 2, 3, 4, 5) // ?
Function.prototype.call()
可將 argument 傳給 function 執行,但此時 this
指向 function 為 undefined
,需透過 bind()
將 Array.prototype.slice
傳進產生新 function。
此為 ECMAScript 由 method 轉 function 慣用手法
let slice = (_ => {}).call.bind([].slice)
let fn = function() {
return slice(arguments, 1, 3)
}
fn(1, 2, 3, 4, 5) // ?
Function.prototype
亦可使用 (_ => {})
arrow function 取代,而 Array.prototype
則以 []
取代。
Conclusion
slice()
是真的 copy array,唯 ECMAScript 都是 shallow copy- Array-like object 透過
Array.prototype.[method].call()
借用 method 乃 ECMAScript 慣用手法 - 藉由
Function.prototype.call.bind()
將 method 轉 function 亦為 ECMAScript 慣用手法