開(kāi)始
JS的數(shù)組中有很多API,其中包括很多ES6新增的方法诸尽,每個(gè)API的的傳參椎例,返回值以及是否會(huì)修該原數(shù)組有很大不同挨决,如果能從原理角度,并且依賴(lài)js實(shí)現(xiàn)該方法订歪,就可以更加熟練它的使用凰棉。下面我們就按著MDN 上的介紹依次實(shí)現(xiàn)。
MDN數(shù)組鏈接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
數(shù)組方法
Array.from
概念
Array.from() 方法從一個(gè)類(lèi)似數(shù)組或可迭代對(duì)象創(chuàng)建一個(gè)新的陌粹,淺拷貝的數(shù)組實(shí)例撒犀。
實(shí)現(xiàn)
思路:
- 數(shù)組的靜態(tài)方法,所以定義
Array._from=function(xxx){}
- 數(shù)組掏秩,類(lèi)數(shù)組對(duì)象或舞,可迭代對(duì)象都實(shí)現(xiàn)
Symbol.iterator
,只有實(shí)現(xiàn)該方法蒙幻,才能實(shí)現(xiàn)遍歷映凳,所以我們可以依賴(lài)該方法來(lái)實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的遍歷。
Array._from=function(target,fn){
let data=target;
if(typeof data[Symbol.iterator]!='function')
{
return [];
}
if(typeof fn!=='function')
{
fn=false;
}
// 必須實(shí)現(xiàn)迭代器
const it= data[Symbol.iterator](),res=[];
let end=false;
while (!end)
{
let {value,done}=it.next();
if(!done)
{
if(fn){
res.push(fn(value))
}
else{
res.push(value);
}
}
end=done;
}
return res
}
測(cè)試
let a='1111',b=10,c=new Set([1,2,3])
console.log(Object.getOwnPropertySymbols(a.__proto__)) //
console.log(Array._from(a))
console.log(Object.getOwnPropertySymbols(b.__proto__)) //[] 數(shù)字沒(méi)有實(shí)現(xiàn)遍歷器邮破,所以返回空數(shù)組
console.log(Array._from(b)) //[]
console.log(Object.getOwnPropertySymbols(c.__proto__)) //[ Symbol(Symbol.toStringTag), Symbol(Symbol.iterator) ]
注意
從測(cè)試結(jié)果可以看出 是否可以被轉(zhuǎn)成數(shù)組诈豌,關(guān)鍵取決于目標(biāo)對(duì)象原型上實(shí)現(xiàn)是否實(shí)現(xiàn)了Symbol(Symbol.iterator)
Array.isArray()
作用
Array.isArray() 用于確定傳遞的值是否是一個(gè) Array。
實(shí)現(xiàn)
思路
- 數(shù)組上的靜態(tài)方法抒和。定義 Array._isArray
- 我們依賴(lài)
Object.prototype.toString
檢驗(yàn)是否是數(shù)組矫渔。
代碼
Array._isArray=function (target) {
return Object.prototype.toString.call(target).slice(8,-1)==='Array'
}
測(cè)試
很簡(jiǎn)單沒(méi)有多余可說(shuō)的
console.log(Array._isArray([1])); //true
console.log(Array._isArray(1)); // false
Array.of
作用
Array.of() 方法創(chuàng)建一個(gè)具有可變數(shù)量參數(shù)的新數(shù)組實(shí)例,而不考慮參數(shù)的數(shù)量或類(lèi)型摧莽。
注意:其實(shí)和Array 區(qū)別不大庙洼,就是單個(gè)參數(shù)有所不同
Array.of(6) //[6]
Array(6) [empty × 6]
思路
- 數(shù)組的靜態(tài)方法
- 將argument(也是類(lèi)數(shù)組對(duì)象)可以使用for遍歷
實(shí)現(xiàn)
Array._of=function(){
console.log(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3 }
let arr=[];
for(let item of arguments)
{
arr.push(item)
}
return arr;
}
測(cè)試
Array._of(1,2,3) //[1,2,3]
Array._of(1) //[1]
Array.prototype.concat()
concat() 方法用于合并兩個(gè)或多個(gè)數(shù)組。此方法不會(huì)更改現(xiàn)有數(shù)組镊辕,而是返回一個(gè)新數(shù)組油够。
示例
console.log([].concat(1,2)); //[ 1, 2 ]
console.log([3].concat(1,[2])); //[ 3, 1, 2 ]
console.log([].concat(1,2,[3,[4]])); [ 1, 2, 3, [ 4 ] ]
console.log(Array.prototype.concat(1,2,[3,4])) // [1,2,3,4]
思路
- 數(shù)組原型上方法 需要 定義
Array.prototype._concat=function(){}
- 可以合并多個(gè)對(duì)象
- 合并對(duì)象如果是數(shù)組征懈,會(huì)扁平化第一層石咬。
- 返回一個(gè)新數(shù)組,不改變?cè)瓟?shù)組
我們根據(jù)如下分析來(lái)逐步實(shí)現(xiàn)
實(shí)現(xiàn)方法
Array.prototype._concat=function () {
let target=this instanceof Array?this:[];
//將形參轉(zhuǎn)為數(shù)組(slice 下一節(jié)我們會(huì)實(shí)現(xiàn))
let args=Array.prototype.slice.call(arguments);
//生成一個(gè)新數(shù)組
let res=[];
while(target.length>0)
{
res.push(target.shift())
}
//對(duì)于需要合并對(duì)象 數(shù)組
while(args.length>0)
{
let value=args.shift();
//扁平化
if(value instanceof Array)
{
for(let item of value)
{
res.push(item);
}
}
//直接插入
else{
res.push(value);
}
}
return res;
}
測(cè)試
同樣我們可以得到如下結(jié)果
console.log([]._concat(1,2)); //[ 1, 2 ]
console.log([3]._concat(1,[2])); //[ 3, 1, 2 ]
console.log([]._concat(1,2,[3,[4]])); //[ 1, 2, 3, [ 4 ] ]
Array.prototype.entries()
作用
entries() () 方法返回一個(gè)新的Array Iterator對(duì)象卖哎,該對(duì)象包含數(shù)組中每個(gè)索引的鍵/值對(duì)鬼悠。
keys() 方法返回一個(gè)包含數(shù)組中每個(gè)索引鍵的Array Iterator對(duì)象虏束。
values() 方法返回一個(gè)新的 Array Iterator 對(duì)象,該對(duì)象包含數(shù)組每個(gè)索引的值厦章。
以上三個(gè)方法原理一樣镇匀,我們?cè)谶@實(shí)現(xiàn)entries() 方法。
思路
- 數(shù)組原型上已經(jīng)實(shí)現(xiàn)
Symbol.iterator
遍歷器方法袜啃,只需要獲得它并執(zhí)行就能得到
實(shí)現(xiàn)
Array.prototype._entries=function(){
let arr=[];
for(let i=0;i<this.length;i++)
{
arr.push([i,this[i]])
}
//新數(shù)組執(zhí)行
return arr[Symbol.iterator]();
}
測(cè)試
也沒(méi)啥可多說(shuō)的
const array1 = ['a', 'b', 'c'];
const iterator1 = array1._entries();
console.log(iterator1.next().value);
// expected output: Array [0, "a"]
console.log(iterator1.next().value);
結(jié)語(yǔ)
先總結(jié)以上五個(gè)方法汗侵,以上方法總體來(lái)說(shuō)還是相對(duì)比較簡(jiǎn)單的,下一繼續(xù)根據(jù)MDN上的介紹和用法依次進(jìn)行總結(jié)群发。