深入研究数组与伪数组

目录

前言

一、伪数组的概念 

二、常见的伪数组 

1、函数中存储所有实参的arguments对象

 2、DOM提供的获取页面节点的方法

三、 数组与伪数组的区别

四、判断伪数组 

五、伪数组转为真数组 


前言

在学习数组方法后,对数组的理解更加深刻了。但是在javascript中存在伪数组的概念,那么伪数组是什么?与数组是什么关系?伪数组的“伪”体现在哪里呢?这篇文章就来学习一下伪数组吧!

一、伪数组的概念 

伪数组是一种按照索引存储数据且具有 length 属性的对象

具有以下特点:

1、可以使用索引对数据进行操作;

2、具有length(长度)属性;

3、但是不能使用数组的方法,如push,pop等数组方法

举个手写的伪数组例子: 

var arrayLike = {
  0: "x",
  1: "y",
  2: "z",
  length: 3,
};

二、常见的伪数组 

1、函数中存储所有实参的arguments对象

function fn() {
            console.dir(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
        }
fn(1,2,3,4);

 2、DOM提供的获取页面节点的方法

2.1document.querySelectorAll()获取到的NodeList 对象

var lis = document.querySelectorAll('li');
        console.log(lis);//NodeList(4) [li, li, li, li]
        lis.forEach(function (value) {
            console.log(value);//lis内所有元素
        })

注意:NodeList 对象是文档节点的集合,具有forEach方法,但不具有其他数组方法

2.2 document.getElementsByClassName()、getElementsByTagName()、node.children等等获取到的HTMLCollection对象

var lis = document.getElementsByClassName('cat');
        console.log(lis);//HTMLCollection(4) [li.cat, li.cat, li.cat, li.cat]
        lis.forEach(function (value) {
            console.log(value);//Uncaught TypeError: lis.forEach is not a function
        })
var lis = document.getElementsByTagName('li');
        console.log(lis);//HTMLCollection(4) [li.cat, li.cat, li.cat, li.cat]
        lis.forEach(function (value) {
            console.log(value);//Uncaught TypeError: lis.forEach is not a function
        })

注意:HTMLCollection对象是文档元素节点的集合,不具有任何数组方法 

除此之外,还有很多常用的伪数组,就不一一列举。 

三、 数组与伪数组的区别

1、伪数组与数组都属于对象,但是伪数组是基于Object构造函数创建的,数组是基于Array构造函数创建的。构造函数的方法写在其原型对象prototype开辟的内存内,基于构造函数创建的对象会拥有其方法。Object构造函数属于最顶级对象,因此根据原型链,伪数组只能拥有Object.prototype 的属性值,不能拥有Array.prototype 的属性值,因此不具有数组的方法。

var obj = {};// 拥有Object.prototype的属性值
var arr = [];//同时拥有Array.prototype和Object.prototype的属性值

2、伪数组的长度作为对象的一个属性,不会随索引属性的改变而改变。 

四、判断伪数组 

1、instanceof()

 var arrayLike = {
                0: "x",
                1: "y",
                2: "z",
                length: 3,
            };
var arr=[1,2,3,4];
console.log(arrayLike instanceof Array);//false
console.log(arr instanceof Array);//true

2、Array.isArray()

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [1, 2, 3, 4];
console.log(Array.isArray(arrayLike));//false
console.log(Array.isArray(arr));//true

3、《javascript权威指南》判断一个对象是否属于“类数组”

function isArrayLike(o) {   
    if (o &&                                // o is not null, undefined, etc.
            typeof o === 'object' &&            // o is an object
            isFinite(o.length) &&               // o.length is a finite number
            o.length >= 0 &&                    // o.length is non-negative
            o.length===Math.floor(o.length) &&  // o.length is an integer
            o.length < 4294967296)              // o.length < 2^32
            return true;                        // Then o is array-like
    else
            return false;                       // Otherwise it is not
}

 4、Array.prototype.isPrototypeOf(),用于测试一个对象是否存在于另一个对象的原型链上。

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [1, 2, 3, 4];
console.log(Array.prototype.isPrototypeOf(arrayLike));  // false
console.log(Array.prototype.isPrototypeOf(arr));  // true

5、__proto__.constructor,判断对象隐式原型的构造函数 

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [1, 2, 3, 4];
console.log(arrayLike.__proto__.constructor);//ƒ Object() { [native code] }
console.log(arr.__proto__.constructor);//ƒ Array() { [native code] }

6、Object.prototype.toString.call()方法,传递要检查的对象作为第一个参数,称为 thisArg

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [1, 2, 3, 4];
console.log(Object.prototype.toString.call(arrayLike));  //[object Object] 
console.log(Object.prototype.toString.call(arr));   //[object Array]

五、伪数组转为真数组 

1、Array.from()

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr=Array.from(arrayLike);
console.log(Array.isArray(arr));//true

2、 slice()  

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [].slice.call(arrayLike);
console.log(Array.isArray(arr));//true

3、concat() 

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr = [].concat.apply([], arrayLike);
console.log(Array.isArray(arr));//true

4、利用for循环遍历 

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 5,
        };
        var arr = [];
        for (var i = 0; i < arrayLike.length; i++) {
            arr.push(arrayLike[i]);
        }
        console.log(arr);// ['x', 'y', 'z']

5、扩展运算符

const el = [...document.querySelectorAll('p')];

console.log(el);// (3) [p, p, p]

注意:以上方法实现的原理都是通过拷贝伪数组,将其值添加到一个新数组中,完成真数组的转换,这些拷贝都是浅拷贝。如果伪数组中包含引用数据类型,新数组与伪数组对值的更改会互相影响。

6、封装函数,实现深拷贝伪数组 

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            3: [100, 200],
            length: 4,
        };
        var arr = [];
        // 封装函数 
        function deepCopy(newobj, oldobj) {
            for (var k in oldobj) {
                // 判断我们的属性值属于那种数据类型
                // 1. 获取属性值  oldobj[k]
                var item = oldobj[k];
                // 2. 判断这个值是否是数组
                if (item instanceof Array) {
                    newobj[k] = [];
                    deepCopy(newobj[k], item)//数组循环时,k为索引值,item为数组本身,newobj[0]='pink',newobj[1]=red;全部复制完后结束
                } else if (item instanceof Object) {
                    // 3. 判断这个值是否是对象
                    newobj[k] = {};
                    deepCopy(newobj[k], item)
                } else {
                    // 4. 属于简单数据类型
                    newobj[k] = item;//第一次循环:k='id',item=1,将新对象属性值=旧对象属性值,同时新对象也创建了新属性
                }

            }
        }
        deepCopy(arr, arrayLike);
        console.log(arr);//['x', 'y', 'z', [100,200]]
        arr[3][0] = 1000;
        console.log(arr);// ['x', 'y', 'z', [1000,200]]
        console.log(arrayLike);//{0: 'x', 1: 'y', 2: 'z', 3: [100,200], length: 4}未改变伪数组中的值
        for (var i = 0; i < arr.length; i++) {
            console.log(arr[i]);//x y z [1000,200]
        }

  • 30
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值