JavaScript中伪数组和数组以及转化

JavaScript中伪数组和数组以及转化

之前看到过一个经典的面试题 说如何将伪数组转成数组 当时一脸懵逼 如今学会了高级JS然后再次看这个问题 好像没有想象中那么难。

伪数组和数组

在JavaScript中,除了5种原始数据类型之外,其他所有的都是对象,包括函数(Function)。

对象与数组的关系

首先你得确保你知道原型链以及原型得继承。

我们都知道所有的JS内置构造函数的对象原型都指向的是Object的原型对象(Object.prototype)。(也可理解为 继承自Object.prototype)

在这个前提下,可以理解为使用new Araay() 或 [ ] 创建出来的数组对象,都会拥有Object.prototype 的属性值。

var obj = {};// 拥有 Object.prototype 
var arr = [];
//使用数组直接量创建的数组,由于 Array.prototype 的属性继承自 Object.prototype,
//那么,它将同时拥有 Array.prototype 和 Object.prototype

可以得到对象和数组的第一个区别:对象没有数组 Array.prototype 的属性值。

什么是数组

数组具有一个最基本特征:索引,这是对象所没有的,下面来看一段代码:

var obj = {};
var arr = [];
 
obj[2] = 'a';
arr[2] = 'a';
 
console.log(obj[2]); // => a
console.log(arr[2]); // => a
console.log(obj.length); // => undefined
console.log(arr.length); // => 3

obj[2]输出’a’,是因为对象就是普通的键值对存取数据
而arr[2]输出’a’ 则不同,数组是通过索引来存取数据,arr[2]之所以输出’a’,是因为数组arr索引2的位置已经存储了数据
obj.length并不具有数组的特性,并且obj没有保存属性length,那么自然就会输出undefined
而对于数组来说,length是数组的一个内置属性,数组会根据索引长度来更改length的值
为什么arr.length输出3,而不是1
因为在给数组添加元素时,并没有按照连续的索引添加,所以导致数组的索引不连续,那么就导致索引长度大于元素个数

什么是伪数组

  1. 拥有 length 属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)
  2. 不具有数组所具有的方法

伪数组,就是像数组一样有 length 属性,也有 0、1、2、3 等属性的对象,看起来就像数组一样,但不是数组,比如:

var obj = {
    0: 5,
    1: 8,
    2: 4,
    3: 6,
    lenngth:4
};

常见的伪数组有:

  • 函数内部的 arguments
  • DOM 对象列表(比如通过 document.getElementsByTags 得到的列表)
  • jQuery 对象(比如 $("div")

伪数组是一个 Object,而真实的数组是一个 Array。

因为在原型链中没有Array.prototype这一环,所以他没有操作数组的方法push,pop,shift,unshift等。javaScript中常见的伪数组对象有以nodeList为原型的DOM对象,函数的参数arguments对象等。

那么有没有方法将这些伪数组对象转换成数组,从而直接使用push,pop等方法来对其进行操作呢?

下面我将介绍五种方法

讲伪数组转换成数组的方法

ES5提供了二种方法:

var obj=document.querySelectorAll('div');
// 方法1
var arr1=new Array();
arr1=arr1.__proto__.slice.call(obj);
console.log(arr1);

// 方法2
var arr2=new Array();
arr2=Array.prototype.slice.call(obj);
console.log(arr2);

// 为什么可以这样写?
// 因为实例对象的原型指向 构造函数的对象原型 也就是说 arr2.__proto__ === Array.prototype  
// 我们知道Array中有一个方法是slice(start,end) 不填就表示逐个分割 
// call改变this指向
arrayObject.slice(start,end)
参数描述
start必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

ES6提供了两种方法:

// 方法3
var arr3=new Array();
var arr3=Array.from(obj);
console.log(arr3);

// 这里的obj是部署 Iterator 接口的数据类型,所以也可以用以下扩展运算符的方式实现转换:
// 方法4
var arr4=[...obj];
console.log(arr4);
// 如果是没有部署iterator接口的数据类型,如下面的ArrayLikeObject, 则不适用以下方法,会直接报错
// 因此这里用扩展运算符的实现中肯定用到了for of来进行遍历。

var ArrayLikeObj = {"0": 1, "1": 2, length: 2}
var result = [...ArrayLikeObj ]
console.log(result)  //报错

img

最后一种方法那就是简单粗暴

var arr5=new Array();
for(var k in obj)
{
	arr5.push(obj[k]);
}
console.log(arr5);

特例

如果我们遇到的知识一个对象没有length长得怎么办呢 我们可以利用for in来做

var obj = {
    0: 5,
    1: 8,
    2: 4,
    3: 6,
};
var arr1=new Array();
for( var k in obj)
{
	arr1.push(obj[k]);
}
console.log(arr1);
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值