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

資訊專欄INFORMATION COLUMN

JavaScript 特殊對象 Array-Like Objects 詳解

zhaofeihao / 605人閱讀

摘要:很簡單,不是數組,但是有屬性,且屬性值為非負類型即可。至于屬性的值,給出了一個上限值,其實是感謝同學指出,因為這是中能精確表示的最大數字。如何將函數的實際參數轉換成數組

這篇文章拖了有兩周,今天來跟大家聊聊 JavaScript 中一類特殊的對象 -> Array-Like Objects。

(本文節(jié)選自 underscore 源碼解讀系列文章,完整版請關注 https://github.com/hanzichi/underscore-analysis)

Array-Like

JavaScript 中一切皆為對象,那么什么是 Array-Like Objects?顧名思義,就是像數組的對象,當然,數組本身就是對象嘛!稍微有點基礎的同學,一定知道 arguments 就是 Array-Like Objects 的一種,能像數組一樣用 [] 去訪問 arguments 的元素,有 length 屬性,但是卻不能用一些數組的方法,如 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;
};

很簡單,不是數組,但是有 length 屬性,且屬性值為非負 Number 類型即可。至于 length 屬性的值,underscore 給出了一個上限值 MAX_ARRAY_INDEX,其實是 MAX_SAFE_INTEGER(感謝 @HangYang 同學指出) ,因為這是 JavaScript 中能精確表示的最大數字。

想想還有什么同時能滿足以上條件的?NodeList,HTML Collections,仔細想想,甚至還有字符串,或者擁有 length 屬性的對象,函數(length 屬性值為形參數量),等等。

Array-Like to Array

有的時候,需要將 Array-Like Objects 轉為 Array 類型,使之能用數組的一些方法,一個非常簡單粗暴并且兼容性良好的方法是新建個數組,然后循環(huán)存入數據。

我們以 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);

如果非得追求性能,用 [] 會新建個數組,性能肯定不及前者,但是由于引擎的優(yōu)化,這點差異基本可以忽略不計了(所以很多框架用的就是后者)。

為什么這樣可以轉換?我們簡單了解下,主要的原因是 slice 方法只需要參數有 length 屬性即可。首先,slice 方法得到的結果是一個 新的數組,通過 Array.prototype.slice.call 傳入的參數(假設為 a),如果沒有 length 屬性,或者 length 屬性值不是 Number 類型,或者為負,那么直接返回一個空數組,否則返回 a[0]-a[length-1] 組成的數組。(具體可以看下 v8 源碼 https://github.com/v8/v8/blob/master/src/js/array.js#L621-L660)

當然,ES6 提供了更簡便的方法。

var str = "helloworld";
var arr = Array.from(str); 
// ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

小結下,如果要把 Array-Like Objects 轉為 Array,首選 Array.prototype.slice,但是由于 IE 下 Array.prototype.slice.call(nodes) 會拋出錯誤(because a DOM NodeList is not a JavaScript object),所以兼容的寫法如下。(但還有一點要注意的是,如果是 arguments 轉為 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

很多時候,某個方法你以為接收的參數是數組,其實類數組也是可以的。

Function.prototype.apply() 函數接收的第二個參數,其實也可以是類數組。

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

如何將函數的實際參數轉換成數組

how does Array.prototype.slice.call() work?

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

轉載請注明本文地址:http://systransis.cn/yun/79777.html

相關文章

  • JavaScript深入淺出

    摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據說是阿里的前端妹子寫的) this 的值到底...

    blair 評論0 收藏0
  • JavaScript arguments 對象全面介紹

    摘要:事實上,滿足一定條件的對象都能被方法轉換成數組。繼承于的很大原因是不需要這四個方法。而在非嚴格模式下,兩個會互相影響。數組與類數組對象數組具有一個基本特征索引。這是一般對象所沒有的。是利用對象的鍵值對存取數據,而卻是利用數組的索引。 1. 什么是 arguments MDN 上解釋: arguments 是一個類數組對象。代表傳給一個function的參數列表。 我們先用一個例子直觀了...

    HackerShell 評論0 收藏0
  • 譯文: JavaScript中類數組對象

    摘要:所以我說的這些類數組對象是什么它們有一些,其中包括是一個很特殊的變量,你再所有函數體內都可以訪問到。讓類數組對象成為一個數組當然這個標題是不太準確的,假如我們需要將這些類數組對象變成數組一樣,我們需要建立一個新的數組。 它看起來像是一個數組,而且它有一個length屬性,然而它并不是一個數組。JavaScript有時候是一門很怪異的語言,因為你很難定義一個數組的概念而沒有什么例外的。所...

    lbool 評論0 收藏0
  • JavaScript 系列--JavaScript一些奇淫技巧的實現(xiàn)方法(二)數字格式化;類數組轉數

    摘要:一前言之前寫了一篇文章系列一些奇淫技巧的實現(xiàn)方法一簡短的函數,獲取時間戳介紹了函數和獲取時間戳的方法。,和對象的構造函數是對象的屬性。缺點低版本,無法處理集合的轉數組。 一、前言 之前寫了一篇文章:JavaScript 系列--JavaScript一些奇淫技巧的實現(xiàn)方法(一)簡短的sleep函數,獲取時間戳 https://www.mwcxs.top/page/74... 介紹了sle...

    Jrain 評論0 收藏0
  • ES6 變量聲明與賦值:值傳遞、淺拷貝與深拷貝詳解

    摘要:變量聲明與賦值值傳遞淺拷貝與深拷貝詳解歸納于筆者的現(xiàn)代開發(fā)語法基礎與實踐技巧系列文章。變量聲明在中,基本的變量聲明可以用方式允許省略,直接對未聲明的變量賦值。按值傳遞中函數的形參是被調用時所傳實參的副本。 ES6 變量聲明與賦值:值傳遞、淺拷貝與深拷貝詳解歸納于筆者的現(xiàn)代 JavaScript 開發(fā):語法基礎與實踐技巧系列文章。本文首先介紹 ES6 中常用的三種變量聲明方式,然后討論了...

    snowLu 評論0 收藏0

發(fā)表評論

0條評論

zhaofeihao

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<