真数组、伪数组的转换和区别(Array.prototype.slice.call())

当我们了解伪数组之前先了解下普通的数组的特点

数组是用来存储一系列值的一个集合,而每个值在数组里面都有一个对应的索引,也可以叫做下标,索引是从0开始的,依次递增。
比如:

let arr = ['a','b','c'];
// 字符串a,b,c对应的下标分别为0, 1, 2,使用 数组名字[索引] 的方法即可取到对应的值。

数组的length为数组当中所存值的总个数,比如上方定义的arr数组的length就是3。

伪数组的介绍:

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

所以我们大概可以这样分辨伪数组:

1、伪数组是一个对象。
2、这个对象必须要有length属性。且必须是number类型。
3、如果这个对象的length不为0,那么必须要有按照下标存储的数据。
4、伪数组不可以使用数组中的方法(.forEach)。
5、但是伪数组的长度不可变。真数组的长度是动态可变的。

// 是真数组
var obj = {};
var obj = { length: 3 };

// 是伪数组
var obj4 = { 0: '12', length: 1 };
var obj5 = { 99: 'abc', length: 100 }

伪数组我们可以理解为类似数组的一个集合,我们常见的有俩个,一个是arguments还有一个是DOM的children属性,获取回来的子节点集合。他们与数组一样,具有索引(下标)和length属性。可以通过for循环写循环语句去循环遍历。我们可以简单看一下伪数组的样子:
在这里插入图片描述

 在这里插入图片描述

伪数组与数组的区别:

伪数组与数组的区别就是它们的_proto_区别,
普通数组有很多数组的方法,比如说push,shift,map等等,详见:

数组常用方法总结(上)
数组常用方法总结(下)
ES5新增数组遍历迭代的方法
而伪数组却没有,所以我们称这类解构类似数组却没有数组方法的集合叫做伪数组。

将伪数组变成真数组的方法:

方法一:

  • 1.Array.prototype.slice.call( 数据 )
// 假设我们获取到了一个一个页面的所有div,这就是一个伪数组。
const fakeArr = document.getElementsByTagName('div');
// 我们可以进行重新赋值也可以用一个新变量接收或者在上方就进行转换简写都可以,笔者拿个新变量接收他。
// 如果你要重新赋值别忘了将const变成let。
const realArr = Array.prototype.slice.call(fakeArr);

方法二:

  • 2.使用ES6中Array.from方法
var obj ={0:"1",
    length: 1 };
    var  newarr= Array.from(obj)
    console.log(obj);
    newarr[1]="123"
    console.log(newarr);

将伪数组obj转标准数组newarr。

对 Array.prototype.slice.call() 和 Array.prototype.slice.apply() 的简要理解

1. 逐步拆分解析

slice:可从已有的数组中返回选定的元素,不改变原数组。
注:有关 splice 方法的详解可参考 有关 Array.prototype.slice() 方法的详解
Array:Array 是 javascript 的一个引用类型,Array.prototype 属性表示 Array 构造函数的原型,其上有一个方法叫 slice()。
注:因此, Array.prototype.slice.call(arguments, 1) 也可以写成 [].slice.call(arguments, 1)
call 和 apply : 可以简单理解为用来改变对象中函数内部的 this 引用指向。apply() 和 call() 方法的第一个参数都是特定的作用域,用来替换对象函数中的 this;第二个参数都是要传递给对象函数的参数,不同之处是 apply() 的第二个参数可以是数组实例或 arguments 类数组对象,call() 则需要逐个列出需要传递的参数。


2. 原理(此处以 call 为例说明)

call 的官方解释:“调用一个对象的一个方法【对象.方法.call()】,以另一个对象替换当前对象。”
  Array.prototype.slice.call(arguments, number) 的原理为:首先第一个参数 arguments 改变数组的 slice() 方法的作用域(即 this 的指向),使 this 指向 arguments 对象,然后 call() 方法的第二个参数 number 作为传递给 slice() 的参数(截取数组的起始位置)。

  进行上述操作后, arguments 类数组(伪数组)就可以使用数组的方法 slice() 了(伪数组并不是真正的数组,是不可以使用 Array 的相关方法的)。

总结起来可简单理解为: Array.prototype.slice.call(arguments, number) 能够将具有 length 属性(必须包含 length 属性)的对象转换为数组,其意义就在于它能将函数的参数对象转化为一个真正的数组。


那我们具体一个 如何判断数据是不是伪数组呢?

  • 1、看是不是对象,不是对象,就可以排除
  • obj是对象
     var obj ={0: '1', length: 1 };
         console.log(typeof(obj));
    
  • 2、是对象,没有length属性也可以排除。
    例子一: 有length属性。
     var obj ={0: '1', length: 1 };
         console.log(obj);
    

    例子二::没有length属性。

     var obj ={0: '1'};
         console.log(obj);
    
  • 3、有length,值必须是number类型。不是的话,可以排除。
  • 有length,但是值必须是string类型。
     var obj ={0: '1', length: "1"};
         console.log(obj);
    
  • 4、length值是number类型,并且值不为0,这个对象还得按照下标存储数据。
     var obj = { length: 0 };
         console.log(obj);
    
  • 5、伪数组不能使用数组所具有的push,pop等方法。
  • 常见的伪数组有:
    1.document.getElementsByTagName和document.childNodes,返回NodeList对象的都是伪数组。
    2.function的arguments对象。
    3.上传文件时选择的file对象也是伪数组。

猜你喜欢

转载自blog.csdn.net/qq_51066068/article/details/126758011
今日推荐