ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

js中伪数组转真数组

2021-03-22 16:04:45  阅读:160  来源: 互联网

标签:console ali li 数组 push 转真 中伪 hello


一、什么是真数组(数组)

所谓真数组,其实可以直接称为:数组。
当一个对象具有以下特点时,可以称为数组:

  • 可以按照索引的方式,存储多个数组
  • 具有length属性,表示数组内数据的长度(个数)
  • 对象的原型属性__proto__,指向Array类,且可以使用Array的原型对象prototype身上的属性和方法,如:push,pop等。如图1:

图1:真数组

二、什么是伪数组

所谓伪数组,当一个对象具有以下特点:

  • 具有length(长度)属性;
  • 可以使用索引对数据进行操作;
  • 但是不能使用数组的方法,如push,pop等。如图2:

图2:伪数组

注意:

  1. 伪数组一般不会直接创建,而是通过一些js操作得到,如:document.getElementsByName()等;
  2. 因为伪数组具有长度和索引,所以可以使用循环语句遍历;
  3. 并不是能使用***部分***数组的方法,就是称为真数组;如图3:

图3:依然是伪数组

  1. 有些情况下,并不是将伪数组的原型__proto__属性设置为Array的原型对象prototype,就可以使用数组的方法。如图4:
    图4:还是伪数组

三、如何将伪数组转成真数组

如果在一些情况下,js给我们返回的是伪数组,但是我们想使用真数组的方法对之进行操作,那么此时就需要将伪数组转成真数组之后,才能继续使用。

接下来我们根据伪数组和真数组的区别和特点,对伪数组做一下改造,将伪数组转成真数组,以完成后续操作。

方法1:遍历:创建一个空数组,循环遍历伪数组,将遍历出的数据逐一放在空数组中

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = [];           // 先创建空数组
for(var i=0;i<ali.length;i++){  // 循环遍历伪数组
    arr[i] = ali[i];    // 取出伪数组的数据,逐个放在真数组中
}

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法2:使用slice方法:利用Array原型对象的slice方法,配合apply,将slice中的this指向伪数组

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = Array.prototype.slice.apply(ali);

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法3:利用ES6提供的Array的from方法

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = Array.from(ali);

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法4:利用ES6提供的展开运算符(…)

var ali = document.getElementsByTagName('li');
console.log(ali);       // [li, li, li, li]
// ali.push("hello");      // TypeError: ali.push is not a function

var arr = [...ali];

arr.push("hello");
console.log(arr);       // [li, li, li, li, "hello"]

方法5:利用原型的复制:将伪数组的__proto__复制为Array的prototype。但是这种方法有局限性

  • 手动创建具有索引和长度的对象,作为伪数组
var obj = {
    0:"a",
    1:"b",
    2:"c",
    length:3
}
console.log(obj);       // {0: "a", 1: "b", 2: "c", length: 3}
// obj.push();          // TypeError: obj.push is not a function

obj.__proto__ = Array.prototype;

console.log(obj);       // ["a", "b", "c"]
obj.push("hello");
console.log(obj);       // ["a", "b", "c", "hello"]
  • arguments也适用
function fn(){
    var arg = arguments;
    console.log(arg);       // ["a", "b", ...]
    // arg.push("hello");   // TypeError: arg.push is not a function

    arg.__proto__ = Array.prototype;

    arg.push("hello");
    console.log(arg);       // ["a", "b", "hello", ...]
}
fn("a","b");
  • 选择器返回的元素集合不适用,因为就算将元素集合的原型改成了数组原型(如图5),但元素集合本身是***只读***的,依然不能修改
var ali = document.getElementsByTagName('li');
console.log(ali);            // [li, li, li, li]
// ali.push("hello");        // TypeError: ali.push is not a function

ali.__proto__ = Array.prototype;

// ali.push("hello");        // Index property setter is not supported

图5

但是不是意味着,没有修改到原数组的方法就可以使用呢(注意图5,没有length属性)

ali.forEach(val => {
    console.log(val);
});

// 会发现浏览器没执行,原因是此时ali缺少length或length为0
console.log(ali.length);    // 0

需要提前获取ali的length,在修改原型之后再手动设置

var ali = document.getElementsByTagName('li');
console.log(ali);            // [li, li, li, li]
// ali.push("hello");        // TypeError: ali.push is not a function

var len = ali.length;        // 获取初始length
ali.__proto__ = Array.prototype;
ali.length = len;            // 设置给修改原型之后的数组对象

// ali.push("hello");        // Index property setter is not supported
ali.forEach(val => {
    console.log(val);        // 遍历打印数组中的值
});
console.log(ali.length);     // 4

小提示:选择器返回的元素数组,使用复制原型方法,还需要手动设置length属性,且不能使用会改变原数组的方法。


以上。
关于伪数组转真数组的方法或技巧,后期继续补充…
文中如果纰漏,错误,不合理,描述不清晰,不准确等问题,欢迎大家留言指正…

标签:console,ali,li,数组,push,转真,中伪,hello
来源: https://blog.csdn.net/weixin_41636483/article/details/115082200

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有