fezaoduke / fe-practice-hard

晚练课
69 stars 6 forks source link

第 95 期(数据结构-数组):伪数组 #98

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

JavaScript 中有一种特殊的数组————伪数组(或称类数组),它和数组很像,都是对象类型,都有 length 属性,但它又不是真正意义上的数组。它是一种以自然递增的整数做为键名,且定义了 length 表示元素个数的对象。

与数组的区别:

  1. 伪数组没有数组原型链(Array.prototype)上的属性和方法,如 pushslicemap 等;
  2. 数组是基于索引的实现,length 会自动更新,而伪数组是基于键值对实现的,本质是对象。
var array = ['Kitty', 'Mike', 'Paul'];

var arrayLike = {
  0: 'Kitty',
  1: 'Mike',
  2: 'Paul',
  length: 3
};

常见的伪数组有函数内部的 arguments、DOM 对象列表 NodeList、正则表达式 match 方法匹配结果等:

function fn() {
  // {0: "a", 1: "b", 2: "c", length: 3, callee: ƒ fn()}
  console.log(arguments)
}
fn('a', 'b', 'c');

// {0: body, length: 1}
document.querySelectorAll('body');
document.getElementsByTagName('body');

// {0: "abc123", 1: "123", groups: undefined, index: 0, input: "abc123", length: 2}
'abc123'.match(/[a-z]+(\d+)/);

当然我们可以将伪数组转换为数组,使其可以正常使用数组的大部分方法:

var arrayLike = {
  0: 'Kitty',
  1: 'Mike',
  2: 'Paul',
  length: 3
};

// 方法1:扩展运算符
[...arrayLike];

// 方法2:创建数组
Array.from(arrayLike);

// 方法3:concat 生成新数组
Array.prototype.concat.apply([], arrayLike)

// 方法4:借用数组方法(此处以 map 方法为例)
Array.prototype.map.call(arrayLike, function(item) {
  // 遍历数组项
});

// 方法5:借用数组方法精简版
[].prototype.slice(arrayLike);