javascript 類數組

在線的《javascript權威指南》有對該概念的解釋。javascript

那麼,什麼是javascript 類數組呢?html

定義:

  • 擁有length屬性,length-0可隱式轉換爲number類型,而且不大於Math.pow(2,32)(好比:22.33'022'都知足條件)
  • 不具備數組所具備的方法

類數組示例:

var a = {'1':'gg','2':'love','4':'meimei',length:5};
Array.prototype.join.call(a,'+');//'+gg+love++meimei'

非類數組示例:

var c = {'1':2};

沒有length屬性,因此就不是類數組。java

javascript中常見的類數組有arguments對象和DOM方法的返回結果。
好比 document.getElementsByTagName()node

類數組判斷

《javascript權威指南》上給出了代碼用來判斷一個對象是否屬於「類數組」。以下:數組

// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are 
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded 
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {
    if (o &&                                // o is not null, undefined, etc.
        typeof o === 'object' &&            // o is an object
        isFinite(o.length) &&               // o.length is a finite number
        o.length >= 0 &&                    // o.length is non-negative
        o.length===Math.floor(o.length) &&  // o.length is an integer
        o.length < 4294967296)              // o.length < 2^32
        return true;                        // Then o is array-like
    else
        return false;                       // Otherwise it is not
}

書上給的示例代碼判斷條件過於嚴苛,好比如下情形的類數組就沒法經過這段代碼的校驗:ide

var arrLike1 = { length: 1.2 };
var arrLike2 = { length: -10 };
var arrLike3 = { length: '10' };

固然,除卻人爲「造做」因素,正常的length應當是正整數。ui

咱們能夠對照一下:MDN Array.from 的polyfill , 這個方法中對length的判斷能夠看一下。prototype

var toInteger = function (value) {
  var number = Number(value);
  if (isNaN(number)) { return 0; }
  if (number === 0 || !isFinite(number)) { return number; }
  return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1; //此處length應當爲Math.pow(2, 32) - 1
var toLength = function (value) {
  var len = toInteger(value);
  return Math.min(Math.max(len, 0), maxSafeInteger);
};

類數組表現

之因此成爲「類數組」,就是由於和「數組」相似。不能直接使用數組方法,但你能夠像使用數組那樣,使用類數組。code

var a = {'0':'a', '1':'b', '2':'c', length:3};  // An array-like object
Array.prototype.join.call(a, '+');  // => 'a+b+c'
Array.prototype.slice.call(a, 0);   // => ['a','b','c']: true array copy
Array.prototype.map.call(a, function(x) { 
    return x.toUpperCase();
});                                 // => ['A','B','C']:

類數組對象轉化爲數組

有時候處理類數組對象的最好方法是將其轉化爲數組。
有兩種實現方法:htm

1.數組slice方法借用

Array.prototype.slice.call(arrLike)

2.Array.from

Array.from(arrLike)

而後就能夠直接使用數組方法啦。

var a = { '0': 1, '1': 2, '2': 3, length: 3 };
var arr = Array.prototype.slice.call(a); //arr = [ 1, 2, 3  ]

ps: 兩個處理方法存在細節差別,好比處理{length: 1}這個對象時,結果就不同,Array.from處理結果是長度爲1而且填充值爲undefined,而Array.prototype.slice處理結果則相同於new Array(1)

對於IE9之前的版本(DOM實現基於COM),咱們可使用makeArray來實現。

// 僞數組轉化成數組
var makeArray = function(obj) {
    if (!obj || obj.length === 0) {
        return [];
    }
    // 非僞類對象,直接返回最好
    if (!obj.length) {
        return obj;
    }
    // 針對IE8之前 DOM的COM實現
    try {
        return [].slice.call(obj);
    } catch (e) {
        var i = 0,
            j = obj.length,
            res = [];
        for (; i < j; i++) {
            res.push(obj[i]);
        }
        return res;
    }

};

參考:

1.https://www.inkling.com/read/...
2.JavaScript 的怪癖 8:「類數組對象」

相關文章
相關標籤/搜索