深入研究数组与伪数组

时间:2025-05-09 07:37:26

目录

前言

一、伪数组的概念 

二、常见的伪数组 

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() {
            (arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
        }
fn(1,2,3,4);

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

2.()获取到的NodeList 对象

var lis = ('li');
        (lis);//NodeList(4) [li, li, li, li]
        (function (value) {
            (value);//lis内所有元素
        })

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

2.2 ()、getElementsByTagName()、等等获取到的HTMLCollection对象

var lis = ('cat');
        (lis);//HTMLCollection(4) [, , , ]
        (function (value) {
            (value);//Uncaught TypeError:  is not a function
        })
var lis = ('li');
        (lis);//HTMLCollection(4) [, , , ]
        (function (value) {
            (value);//Uncaught TypeError:  is not a function
        })

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

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

三、 数组与伪数组的区别

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

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

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

四、判断伪数组 

1、instanceof()

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

2、()

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

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

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

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

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

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

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

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

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

五、伪数组转为真数组 

1、()

var arrayLike = {
            0: "x",
            1: "y",
            2: "z",
            length: 3,
        };
var arr=(arrayLike);
((arr));//true

2、 slice()  

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

3、concat() 

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

4、利用for循环遍历 

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

5、扩展运算符

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

(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);
        (arr);//['x', 'y', 'z', [100,200]]
        arr[3][0] = 1000;
        (arr);// ['x', 'y', 'z', [1000,200]]
        (arrayLike);//{0: 'x', 1: 'y', 2: 'z', 3: [100,200], length: 4}未改变伪数组中的值
        for (var i = 0; i < ; i++) {
            (arr[i]);//x y z [1000,200]
        }