成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 小技巧之?dāng)?shù)組合并

張率功 / 2316人閱讀

摘要:對(duì)于一些小數(shù)組來(lái)說(shuō),這樣做當(dāng)然沒(méi)有問(wèn)題。第一個(gè)主要問(wèn)題在于,我們將要追加的數(shù)組的元素?cái)?shù)量翻倍了當(dāng)然是臨時(shí)性的,因?yàn)閷?shí)質(zhì)上要將數(shù)組內(nèi)容拷貝到函數(shù)調(diào)用棧上。所以,假如要追加的數(shù)組中有一百萬(wàn)個(gè)元素,那么幾乎一定會(huì)超過(guò)函數(shù)和的調(diào)用棧限制的大小。

原文鏈接: https://davidwalsh.name/combi...

這是一篇介紹 JavaScript 技術(shù)的小短文。我們將會(huì)講到組合/合并兩個(gè)數(shù)組的不同策略,以及每一種方法的優(yōu)缺點(diǎn)。

首先展示一下應(yīng)用場(chǎng)景:

var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ];

很顯然,拼接后的結(jié)果是這個(gè)樣子滴:

[
   1, 2, 3, 4, 5, 6, 7, 8, 9,
   "foo", "bar", "baz", "bam" "bun", "fun"
]

concat(..)

最常見(jiàn)的做法如下:

var c = a.concat( b );

a; // [1,2,3,4,5,6,7,8,9]
b; // ["foo","bar","baz","bam","bun","fun"]

c; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

從上述代碼可以看出,c 是一個(gè)由 ab 兩個(gè)數(shù)組合并而成的全新的數(shù)組,而 ab 則不受影響。相當(dāng)簡(jiǎn)單,對(duì)吧?

假如 ab 分別包含 10,000 元素呢?那么 c 中就會(huì)包含 20,000 個(gè)元素,占用的內(nèi)存基本上讓 ab 占用的內(nèi)存翻倍。

“這沒(méi)什么大不了的!”你微微一笑。我們可以把 ab 刪除嘛,這樣就可以將占據(jù)的內(nèi)存回收了,這樣總可以吧?危機(jī)解除!

a = b = null; // `a` and `b` can go away now

哦。對(duì)于一些小數(shù)組來(lái)說(shuō),這樣做當(dāng)然沒(méi)有問(wèn)題。但是對(duì)于大數(shù)組來(lái)說(shuō),或者經(jīng)常性地執(zhí)行這樣的操作,再或者在執(zhí)行環(huán)境內(nèi)存有限的情況下,這樣做還遠(yuǎn)遠(yuǎn)不夠。

循環(huán)插入

好吧,那使用 Array#push(..) 方法將一個(gè)數(shù)組的內(nèi)容追加到另外一個(gè)數(shù)組呢:

// `b` onto `a`
for (var i=0; i < b.length; i++) {
    a.push( b[i] );
}

a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

b = null;

現(xiàn)在,a 中包含的是原本 a 中的元素外加 b 中的元素。

看起來(lái)對(duì)于內(nèi)存的使用有效多了。

可是假如 a 比較小而 b 相對(duì)來(lái)說(shuō)很大呢?出于內(nèi)存利用以及執(zhí)行速度的考量,你一定希望把小數(shù)組 a 插入到 b 的前面而不是把大數(shù)組 b 追加到 a 后面。沒(méi)問(wèn)題,只要用 unshift(..) 替換 push(..) 然后反方向遍歷就可以了:

// `a` into `b`:
for (var i=a.length-1; i >= 0; i--) {
    b.unshift( a[i] );
}

b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

a = null;
使用函數(shù)小技巧

遺憾的是,for 循環(huán)不夠優(yōu)雅,也不容易維護(hù)。還有沒(méi)有更好的辦法呢?

下面是我們的第一次嘗試,用的是 Array#reduce

// `b` onto `a`:
a = b.reduce( function(coll,item){
    coll.push( item );
    return coll;
}, a );

a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

// or `a` into `b`:
b = a.reduceRight( function(coll,item){
    coll.unshift( item );
    return coll;
}, b );

b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

Array#reduce(..)Array#reduceRight(..) 看起來(lái)不錯(cuò),只是有點(diǎn)笨拙。ES6 中的 => 箭頭表達(dá)式可以對(duì)其進(jìn)行適當(dāng)“瘦身”,但是依然需要對(duì)于每一個(gè)元素進(jìn)行一次函數(shù)調(diào)用,這一點(diǎn)有些令人遺憾。

下面的方法怎么樣呢:

// `b` onto `a`:
a.push.apply( a, b );

a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

// or `a` into `b`:
b.unshift.apply( b, a );

b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]

看起來(lái)好多了,是吧?!尤其是這里的 unshift(..) 不再需要顧及遍歷順序的問(wèn)題。ES6 中的展開(kāi)運(yùn)算符(spread operator)會(huì)更棒:a.push( ...b ) 或是 b.unshift( ...a )。

但是呢,公主與王子并沒(méi)有從此過(guò)上幸福無(wú)虞的生活。在兩種情況下,將 ab 傳給 apply(..) 第二個(gè)參數(shù)(或者通過(guò) ... )展開(kāi)運(yùn)算符意味著數(shù)組需要展開(kāi)為函數(shù)的參數(shù)。

第一個(gè)主要問(wèn)題在于,我們將要追加的數(shù)組的元素?cái)?shù)量翻倍了(當(dāng)然是臨時(shí)性的),因?yàn)閷?shí)質(zhì)上要將數(shù)組內(nèi)容拷貝到函數(shù)調(diào)用棧上。另外,不同的 JS 引擎因?qū)崿F(xiàn)方式的不同,對(duì)于可以傳入函數(shù)的參數(shù)的數(shù)量限制也不盡相同。

所以,假如要追加的數(shù)組中有一百萬(wàn)個(gè)元素,那么幾乎一定會(huì)超過(guò)函數(shù) push(..)unshift(..) 的調(diào)用棧限制的大小。嗯!幾千元素應(yīng)該是沒(méi)有問(wèn)題的,不過(guò)需要小心設(shè)定一個(gè)合理的安全上限。

注意: 你可以嘗試使用 splice(..),但是結(jié)論與 push(..) / unshift(..) 相同。

一個(gè)可行的方式是,依然采用上述方法,將數(shù)組劃分為處于安全范圍的片段,進(jìn)行批處理:

function combineInto(a,b) {
    var len = a.length;
    for (var i=0; i < len; i=i+5000) {
        b.unshift.apply( b, a.slice( i, i+5000 ) );
    }
}

且慢,接下來(lái)我們要回到可讀性(或者還有執(zhí)行效率)的老話題了。我們還是在拋棄當(dāng)前所獲得的所有有效方式之前就此打住吧。

總結(jié)

Array#concat(..) 是合并兩個(gè)(甚至多個(gè))數(shù)組的行之有效的方法。但是隱含的風(fēng)險(xiǎn)是,它直接創(chuàng)建了一個(gè)新的數(shù)組,而不是在原來(lái)數(shù)組的基礎(chǔ)上進(jìn)行修改。

在原來(lái)數(shù)組的基礎(chǔ)上進(jìn)行修改有多種可行的方式,但均有某種程度的妥協(xié)。

從不同方法(包括未在這里展示的方法)的優(yōu)缺點(diǎn)來(lái)看,或許最好的方法就是 reduce(..)reduceRight(..)。

無(wú)論選擇采用哪種方法,都需要對(duì)數(shù)組合并策略進(jìn)行批判性思考,而不是想當(dāng)然。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/88956.html

相關(guān)文章

  • 12個(gè)javaScript技巧

    摘要:如果第一個(gè)參數(shù)返回的值為,那么第二個(gè)值將會(huì)認(rèn)為是一個(gè)默認(rèn)值。但這個(gè)對(duì)象不具有數(shù)組的函數(shù)功能,比如等。 轉(zhuǎn)載自:http://www.w3cplus.com/javasc...英文出處:https://blog.jscrambler.com/1... 12個(gè)JavaScript技巧 在這篇文章中將給大家分享12個(gè)有關(guān)于JavaScript的小技巧。這些小技巧可能在你的實(shí)際工作中或許能幫助...

    AWang 評(píng)論0 收藏0
  • 12個(gè)非常實(shí)用的JavaScript技巧

    摘要:如果第一個(gè)參數(shù)返回的值為,那么第二個(gè)值將會(huì)認(rèn)為是一個(gè)默認(rèn)值。獲取數(shù)組中最后一個(gè)元素用來(lái)獲取和之間的數(shù)組元素。但這個(gè)對(duì)象不具有數(shù)組的函數(shù)功能,比如等。 使用!!操作符轉(zhuǎn)換布爾值 有時(shí)候我們需要對(duì)一個(gè)變量查檢其是否存在或者檢查值是否有一個(gè)有效值,如果存在就返回true值。為了做這樣的驗(yàn)證,我們可以使用!!操作符來(lái)實(shí)現(xiàn)是非常的方便與簡(jiǎn)單。對(duì)于變量可以使用!!variable做檢測(cè),只要變量的...

    jsbintask 評(píng)論0 收藏0
  • 七個(gè) JavaScript 實(shí)用技巧

    摘要:接下來(lái)先介紹七個(gè)馬上就能用起來(lái)的小技巧。老實(shí)講,文章所說(shuō)的小技巧大部分都是新增的語(yǔ)法特性,,或者說(shuō)已經(jīng)發(fā)布好些年頭,這些特性大家可能已經(jīng)非常熟識(shí)。,對(duì)象合并,不多說(shuō),大部分場(chǎng)景可以取代。 作者:@davidwalshblog原文:7 Useful JavaScript Tricks 和許多其他語(yǔ)言一樣,JavaScript 也需要靠很多小技巧去完成各種不同的事情。有的可能早已經(jīng)廣為人...

    Lin_YT 評(píng)論0 收藏0
  • 7個(gè)javascript實(shí)用技巧

    摘要:每種編程語(yǔ)言都有一些黑魔法或者說(shuō)小技巧,也不例外,大部分是借助或者瀏覽器新特性實(shí)現(xiàn)。下面介紹的個(gè)實(shí)用小技巧,相信其中有些你一定用過(guò)。當(dāng)然不管語(yǔ)言如何變化,我們總能在編程中總結(jié)一些小技巧來(lái)精簡(jiǎn)代碼。 showImg(https://segmentfault.com/img/remote/1460000018902642); 每種編程語(yǔ)言都有一些黑魔法或者說(shuō)小技巧,JS也不例外,大部分是借...

    tinysun1234 評(píng)論0 收藏0
  • 原生javascript的一些好用的技巧1

    摘要:以下我經(jīng)常用,又總是記不住的幾個(gè)方法轉(zhuǎn)成數(shù)組形式獲取中的內(nèi)容關(guān)鍵在頁(yè)面標(biāo)簽加載完成事件關(guān)鍵在阻止瀏覽器事件默認(rèn)行為關(guān)鍵,記憶方法阻止事件冒泡關(guān)鍵,記憶方法數(shù)組的幾個(gè)常用方法是數(shù)組的每一項(xiàng)如的下標(biāo),每一個(gè)元素的順序等同于一個(gè)單純的循環(huán)可以對(duì)進(jìn) 以下我經(jīng)常用,又總是記不住的幾個(gè)方法 document.querySelectorAll 轉(zhuǎn)成數(shù)組形式; [].slice.call(docume...

    qujian 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<