摘要:很簡(jiǎn)單,不是數(shù)組,但是有屬性,且屬性值為非負(fù)類(lèi)型即可。至于屬性的值,給出了一個(gè)上限值,其實(shí)是感謝同學(xué)指出,因?yàn)檫@是中能精確表示的最大數(shù)字。如何將函數(shù)的實(shí)際參數(shù)轉(zhuǎn)換成數(shù)組
這篇文章拖了有兩周,今天來(lái)跟大家聊聊 JavaScript 中一類(lèi)特殊的對(duì)象 -> Array-Like Objects。
(本文節(jié)選自 underscore 源碼解讀系列文章,完整版請(qǐng)關(guān)注 https://github.com/hanzichi/underscore-analysis)
Array-LikeJavaScript 中一切皆為對(duì)象,那么什么是 Array-Like Objects?顧名思義,就是像數(shù)組的對(duì)象,當(dāng)然,數(shù)組本身就是對(duì)象嘛!稍微有點(diǎn)基礎(chǔ)的同學(xué),一定知道 arguments 就是 Array-Like Objects 的一種,能像數(shù)組一樣用 [] 去訪問(wèn) arguments 的元素,有 length 屬性,但是卻不能用一些數(shù)組的方法,如 push,pop,等等。
那么,什么樣的元素是 Array-Like Objects?我們來(lái)看看 underscore 中對(duì)其的定義。
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; var getLength = property("length"); var isArrayLike = function(collection) { var length = getLength(collection); return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; };
很簡(jiǎn)單,不是數(shù)組,但是有 length 屬性,且屬性值為非負(fù) Number 類(lèi)型即可。至于 length 屬性的值,underscore 給出了一個(gè)上限值 MAX_ARRAY_INDEX,其實(shí)是 MAX_SAFE_INTEGER(感謝 @HangYang 同學(xué)指出) ,因?yàn)檫@是 JavaScript 中能精確表示的最大數(shù)字。
想想還有什么同時(shí)能滿足以上條件的?NodeList,HTML Collections,仔細(xì)想想,甚至還有字符串,或者擁有 length 屬性的對(duì)象,函數(shù)(length 屬性值為形參數(shù)量),等等。
Array-Like to Array有的時(shí)候,需要將 Array-Like Objects 轉(zhuǎn)為 Array 類(lèi)型,使之能用數(shù)組的一些方法,一個(gè)非常簡(jiǎn)單粗暴并且兼容性良好的方法是新建個(gè)數(shù)組,然后循環(huán)存入數(shù)據(jù)。
我們以 arguments 為例。
function fn() { // Uncaught TypeError: arguments.push is not a function // arguments.push(4); var arr = []; for (var i = 0, len = arguments.length; i < len; i++) arr[i] = arguments[i]; arr.push(4); // [1, 2, 3, 4] } fn(1, 2, 3);
但是這不是最優(yōu)雅的,更優(yōu)雅的解法大家一定都知道了,use Array.prototype.slice(IE9- 會(huì)有問(wèn)題)。
function fn() { var arr = Array.prototype.slice.call(arguments); arr.push(4); // arr -> [1, 2, 3, 4] } fn(1, 2, 3);
或者可以用 [] 代替 Array.prototype 節(jié)省幾個(gè)字節(jié)。
function fn() { var arr = [].slice.call(arguments); arr.push(4); // arr -> [1, 2, 3, 4] } fn(1, 2, 3);
如果非得追求性能,用 [] 會(huì)新建個(gè)數(shù)組,性能肯定不及前者,但是由于引擎的優(yōu)化,這點(diǎn)差異基本可以忽略不計(jì)了(所以很多框架用的就是后者)。
為什么這樣可以轉(zhuǎn)換?我們簡(jiǎn)單了解下,主要的原因是 slice 方法只需要參數(shù)有 length 屬性即可。首先,slice 方法得到的結(jié)果是一個(gè) 新的數(shù)組,通過(guò) Array.prototype.slice.call 傳入的參數(shù)(假設(shè)為 a),如果沒(méi)有 length 屬性,或者 length 屬性值不是 Number 類(lèi)型,或者為負(fù),那么直接返回一個(gè)空數(shù)組,否則返回 a[0]-a[length-1] 組成的數(shù)組。(具體可以看下 v8 源碼 https://github.com/v8/v8/blob/master/src/js/array.js#L621-L660)
當(dāng)然,ES6 提供了更簡(jiǎn)便的方法。
var str = "helloworld"; var arr = Array.from(str); // ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]
小結(jié)下,如果要把 Array-Like Objects 轉(zhuǎn)為 Array,首選 Array.prototype.slice,但是由于 IE 下 Array.prototype.slice.call(nodes) 會(huì)拋出錯(cuò)誤(because a DOM NodeList is not a JavaScript object),所以兼容的寫(xiě)法如下。(但還有一點(diǎn)要注意的是,如果是 arguments 轉(zhuǎn)為 Array,最好別用 Array.prototype.slice,V8 下會(huì)很慢,具體可以看下 避免修改和傳遞 arguments 給其他方法 — 影響優(yōu)化 )
function nodeListToArray(nodes){ var arr, length; try { // works in every browser except IE arr = [].slice.call(nodes); return arr; } catch(err){ // slower, but works in IE arr = []; length = nodes.length; for(var i = 0; i < length; i++){ arr.push(nodes[i]); } return arr; } }Others
很多時(shí)候,某個(gè)方法你以為接收的參數(shù)是數(shù)組,其實(shí)類(lèi)數(shù)組也是可以的。
Function.prototype.apply() 函數(shù)接收的第二個(gè)參數(shù),其實(shí)也可以是類(lèi)數(shù)組。
var obj = {0: 4, length: 2}; var arr = [1, 2, 3]; Array.prototype.push.apply(arr, obj); console.log(arr); // [1, 2, 3, 4, undefined]Read More
How to convert a array-like object to array?
Advanced Javascript: Objects, Arrays, and Array-Like objects
JavaScript quirk 8: array-like objects
如何將函數(shù)的實(shí)際參數(shù)轉(zhuǎn)換成數(shù)組
how does Array.prototype.slice.call() work?
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79777.html
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點(diǎn)提及,但是只要善于運(yùn)用,其實(shí)基于原型的繼承模型比傳統(tǒng)的類(lèi)繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對(duì)方法,包括,,。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 怎樣使用 this 因?yàn)楸救藢儆趥吻岸耍虼宋闹兄豢炊?8 成左右,希望能夠給大家?guī)?lái)幫助....(據(jù)說(shuō)是阿里的前端妹子寫(xiě)的) this 的值到底...
摘要:事實(shí)上,滿足一定條件的對(duì)象都能被方法轉(zhuǎn)換成數(shù)組。繼承于的很大原因是不需要這四個(gè)方法。而在非嚴(yán)格模式下,兩個(gè)會(huì)互相影響。數(shù)組與類(lèi)數(shù)組對(duì)象數(shù)組具有一個(gè)基本特征索引。這是一般對(duì)象所沒(méi)有的。是利用對(duì)象的鍵值對(duì)存取數(shù)據(jù),而卻是利用數(shù)組的索引。 1. 什么是 arguments MDN 上解釋?zhuān)?arguments 是一個(gè)類(lèi)數(shù)組對(duì)象。代表傳給一個(gè)function的參數(shù)列表。 我們先用一個(gè)例子直觀了...
摘要:所以我說(shuō)的這些類(lèi)數(shù)組對(duì)象是什么它們有一些,其中包括是一個(gè)很特殊的變量,你再所有函數(shù)體內(nèi)都可以訪問(wèn)到。讓類(lèi)數(shù)組對(duì)象成為一個(gè)數(shù)組當(dāng)然這個(gè)標(biāo)題是不太準(zhǔn)確的,假如我們需要將這些類(lèi)數(shù)組對(duì)象變成數(shù)組一樣,我們需要建立一個(gè)新的數(shù)組。 它看起來(lái)像是一個(gè)數(shù)組,而且它有一個(gè)length屬性,然而它并不是一個(gè)數(shù)組。JavaScript有時(shí)候是一門(mén)很怪異的語(yǔ)言,因?yàn)槟愫茈y定義一個(gè)數(shù)組的概念而沒(méi)有什么例外的。所...
摘要:一前言之前寫(xiě)了一篇文章系列一些奇淫技巧的實(shí)現(xiàn)方法一簡(jiǎn)短的函數(shù),獲取時(shí)間戳介紹了函數(shù)和獲取時(shí)間戳的方法。,和對(duì)象的構(gòu)造函數(shù)是對(duì)象的屬性。缺點(diǎn)低版本,無(wú)法處理集合的轉(zhuǎn)數(shù)組。 一、前言 之前寫(xiě)了一篇文章:JavaScript 系列--JavaScript一些奇淫技巧的實(shí)現(xiàn)方法(一)簡(jiǎn)短的sleep函數(shù),獲取時(shí)間戳 https://www.mwcxs.top/page/74... 介紹了sle...
摘要:變量聲明與賦值值傳遞淺拷貝與深拷貝詳解歸納于筆者的現(xiàn)代開(kāi)發(fā)語(yǔ)法基礎(chǔ)與實(shí)踐技巧系列文章。變量聲明在中,基本的變量聲明可以用方式允許省略,直接對(duì)未聲明的變量賦值。按值傳遞中函數(shù)的形參是被調(diào)用時(shí)所傳實(shí)參的副本。 ES6 變量聲明與賦值:值傳遞、淺拷貝與深拷貝詳解歸納于筆者的現(xiàn)代 JavaScript 開(kāi)發(fā):語(yǔ)法基礎(chǔ)與實(shí)踐技巧系列文章。本文首先介紹 ES6 中常用的三種變量聲明方式,然后討論了...
閱讀 2267·2023-04-25 14:50
閱讀 1254·2021-10-13 09:50
閱讀 1868·2019-08-30 15:56
閱讀 1847·2019-08-29 15:29
閱讀 2891·2019-08-29 15:27
閱讀 3551·2019-08-29 15:14
閱讀 1198·2019-08-29 13:01
閱讀 3303·2019-08-26 14:06