JS 中數(shù)組常用方法以及它的原理實(shí)現(xiàn)(一)

開(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é)群发。

掘金地址:https://juejin.im/user/5efd45a1f265da22f511c7f3/posts

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晰韵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子熟妓,更是在濱河造成了極大的恐慌雪猪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件起愈,死亡現(xiàn)場(chǎng)離奇詭異只恨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)抬虽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)官觅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人阐污,你說(shuō)我怎么就攤上這事休涤。” “怎么了笛辟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵功氨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我手幢,道長(zhǎng)捷凄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任弯菊,我火速辦了婚禮纵势,結(jié)果婚禮上踱阿,老公的妹妹穿的比我還像新娘管钳。我一直安慰自己,他們只是感情好软舌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布才漆。 她就那樣靜靜地躺著,像睡著了一般佛点。 火紅的嫁衣襯著肌膚如雪醇滥。 梳的紋絲不亂的頭發(fā)上黎比,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音鸳玩,去河邊找鬼阅虫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛不跟,可吹牛的內(nèi)容都是我干的颓帝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼窝革,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼购城!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起虐译,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瘪板,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后漆诽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體侮攀,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年厢拭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魏身。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蚪腐,死狀恐怖箭昵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情回季,我是刑警寧澤家制,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站泡一,受9級(jí)特大地震影響颤殴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鼻忠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一涵但、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帖蔓,春花似錦矮瘟、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至埋酬,卻和暖如春哨啃,著一層夾襖步出監(jiān)牢的瞬間烧栋,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工拳球, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留审姓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓祝峻,卻偏偏與公主長(zhǎng)得像邑跪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呼猪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354