什么是类数组

javascript中一些看起来像却不是数组的对象,叫做类数组。也就是说,为一些常规对象增加一些属性可以使其变成类数组对象。

类数组的特征:

  1. 有索引(数字)属性和length属性的对象
  2. 不具有数组的方法。间接调用数组的一些方法,比如push()可以动态的增长length的值

实际上,类数组的定义只有一条,具有 length属性。

举个例子:

var array = ['name', 'age', 'sex'];//数组

var arrayLike = {
    0: 'name',
    1: 'age',
    2: 'sex',
    length: 3
}//类数组

javascript中常见的比较典型的类数组有两个:arguments对象和一些DOM方法的返回值(如document.getElementsByTagName()

类数组使用数组方法的两种方式

类数组虽然和数组类似,但是不能直接使用数组的方法,可以像使用数组一样,使用类数组。

在ECMAScript5中,所有的数组方法都是通用的 。既然类数组对象没有继承Array.prototype,当然不能再类数组对象上直接调用数组方法。尽管如此,可以使用Function.call方法间接调用;或者在类数组中自定义数组方法,使函数体指向Array.prototype中对应的方法体。

  • 使用Function.call方法间接使用数组的方法
var a = {
   '0': 'a',
   '1': 'b',
   '2': 'c',
   '3': 'd',
   'length': 4
}//类数组对象

Array.prototype.join.call(a, '-') //"a-b-c-d"
Array.prototype.slice.call(a, 0) //["a", "b", "c", "d"] 真正的数组
Array.prototype.map.call(a, function(item){
   return item.toUpperCase()
}) //["A", "B", "C", "D"]

Array.prototype.push.call(a, '1','23')
console.log(a) //{0: "a", 1: "b", 2: "c", 3: "d", 4: "1", 5: "1", 6: "23", length: 7}
  • 在类数组对象中添加数组的方法。通过对象的属性名模拟数组的特性。

一道题目

var obj = {
    '2': 'a',
    '3': 'd',
    'length': 2,
    'push': Array.prototype.push
}
obj.push('c');
obj.push('d');
console.log(obj)//{'2': 'c', '3': 'd', length: 2, push: f}

首先一定要明白push()方法的实现原理。在这里,如果让类数组强行调用push方法,则会根据length属性值的位置进行属性的扩充。

//push()`方法的实现原理
Array.prototype.push = function () {
  for(var i = 0; i < arguments.length; i++) {
    this[this.length] = arguments[i];
  }
  return this.length;
}

//类数组使用push方法, length属性值设为3
var arrayLike = {
    haha: '2rr',
    hehe: 'enen',
    length: 3,
    push : Array.prototype.push
}
arrayLike.push(34);
console.log(arrayLike);

//改变length属性值
var arrayLike = {
    haha: '2rr',
    hehe: 'enen',
    length: 6,
    push : Array.prototype.push
}
arrayLike.push(34, 'hobby');
console.log(arrayLike);

打印结果:
打印结果.png

将类数组转化为真正的数组

有时候处理类数组最好的办法是将其转换成真正的数组。

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// 1. slice
Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"] 
// 2. splice
Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"] 
// 3. ES6 Array.from
Array.from(arrayLike); // ["name", "age", "sex"] 
// 4. apply
Array.prototype.concat.apply([], arrayLike)

一个很温馨的名字
144 声望3 粉丝

FE ren~