什么是伪数组?
伪数组的特点
- 伪数组拥有数组的属性,
- 具有 length 属性 但length属性不是动态的,不会随着成员的变化而变化
- 按索引方式储存数据
- 不具有数组的push(), forEach()等方法
- 伪数组本质是一个 Object,而真实的数组是一个 Array。
- 伪数组的原型
Object.__prototype__
通过改变原型指向可以将伪数组转为真数组
常见伪数组
-
函数内部的 arguments,扩展操作符可以将 arguments 展开成独立的参数
-
DOM 对象列表 如 通过 document.getElementByTags 获取的 dom元素
-
jQuery对象 如 $(‘div’)
-
// 伪数组 var arrLike = { 0: 'a', 1: 'b', 2: 'c', length: 3, };
伪数组转为真数组
-
遍历添加入一个空数组
-
var arr = []; for(var i = 0; i < arrLike.length; i++){ arr.push(arrLike[i]); }
-
利用数组的slice()方法
-
;[].slice.call(arrLike); //slice() 方法以新的数组对象,返回数组中被选中的元素。
-
或者
-
Array.prototype.slice.apply(arrLike);
-
使用slice()返回一个新的数组,用call()或apply()把他的作用环境指向伪数组。slice 返回的数组中,不会保留索引值以外的其他额外属性。
-
模拟 slice() 内部实现 Array.prtotype.slice = function(start, end){ var result = new Array(); var start = start | 0; var end = end | this.length; for(var i = start; i < end; i++){ result.push(this[i]); } return result; }
-
改变原型指向
-
arrLike.__proto__ = Array.prototype;
-
通过改变原型指向,arrLike就继承了Array.prototype中的方法,可以使用push(),unshift()等方法了,length值也会随之动态改变。
-
这种直接修改原型链的方法,还会保留下伪数组中的所有属性,包括不是索引值的属性。
-
Array.from()
-
Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。
-
var arr = Array.from(arrLike);
如何判断数组
-
使用instanceof
-
arr instanceof Array
-
大部分情况都可以用instanceof判断是否是数组,但是在判断一个变量是对象或非对象时,会存在坑,
-
因为 instanceof 在判断数组时,即会把数组当做Array类型,又会把数组当做Object类型,所以要严格验证一个数组,最好是用constructor,能严格区分数组和对象。
-
使用constructor
-
console.log([].constructor == Array); //true console.log({}.constructor == Object); //true console.log("string".constructor == String); //true console.log((123).constructor == Number); //true console.log(true.constructor == Boolean); //true
-
使用Object.prototype.toString.call(arr) === ‘[object Array]’, 重点记住object Array
-
使用Array.isArray 判断
-
Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false Array.isArray("foobar"); // false Array.isArray(undefined); // false