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