JavaScript之伪数组和数组细谈

作者: 费莱姆 | 来源:发表于2021-12-16 23:16 被阅读0次

想成为那种不声不响,但是什么都做得很好的人。

对象与数组的关系

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

JavaScript 的原型继承:
所有 JavaScript 的内置构造函数都是继承自 Object.prototype 。在这个前提下,可以理解为使用 new Array() 或 [] 创建出来的数组对象,都会拥有 Object.prototype 的属性值。

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

结论: 对象没有数组 Array.prototype 的属性值

数组

定义: 数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。只能用整数作为数组元素的索引,而不能用字符串。对象是没有索引的,是数组的基本特征。

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. 伪数组是一个对象(Object),而真实的数组是一个数组(Array)
  2. 拥有length属性,且必须是number类型,其它属性(索引)为字符串
  3. 不具有数组所具有的方法,forEach()等,不过有Object的方法
  4. 伪数组长度不可变,真数组长度可以变
  5. 可以通过for in遍历
var fakeArray = {
    length: 3,
    "0": "first",
    "1": "second",
    "2": "third"
}
var arr = [1, 2, 3, 4]

// 真数组的方法来自Array.prototype
console.log(fakeArray instanceof Array) //false
console.log(arr instanceof Array) // true

Array.isArray(fakeArray) // false;
Array.isArray(arr) // true;

console.log(arr.__proto__ === Array.prototype) // true
console.log(fakeArray.__proto__ === Array.prototype) // false
console.log(fakeArray.__proto__ === Object.prototype) // true

arr.forEach(x => console.log(x)) // 1 2 3 4
fakeArray.forEach(x => console.log(x)) // fakeArray.forEach is not a function

Object.keys(fakeArray) //  ["0", "1", "2", "length"]

常见的伪数组有:

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

伪数组是一个 Object,而真实的数组是一个 Array。
伪数组存在的意义,是可以让普通的对象也能正常使用数组的很多方法,比如:

  1. 使用Array.prototype.slice.call();
var arr = Array.prototype.slice.call(arguments);
 
Array.prototype.forEach.call(arguments, function(v) {
  // 循环arguments对象
});

// push
// some
// every
// filter
// map
// ...
  1. 使用[].slice.call()
var fakeArray = {
    length: 3,
    "0": "first",
    "1": "second",
    "2": "third"
}
var arr = [].slice.call(fakeArray) 
console.log(arr) // ["first", "second", "third"]
  1. 使用ES6中的Array.from方法
var fakeArray = {
    length: 3,
    "0": "first",
    "1": "second",
    "2": "third"
    }
var arr = Array.from(fakeArray)
console.log(arr) // ["first", "second", "third"]
  1. 使用扩展运算符,也是ES6的语法
var fakeArray = document.querySelectorAll('div')
var newArr= [...fakeArray]
console.log(newArr.__proto__ === Array.prototype) // true

伪数组转换为真数组原理

Array.prototype.slice = function (start, end) {
  start = start || 0
  end = start || this.length
  const arr = []
  for (var i = start; i < end; i++) {
    arr.push(this[i])
  }
  return arr
}

结论

  • 对象没有数组 Array.prototype 的属性值,类型是 Object ,而数组类型是 Array
  • 数组是基于索引的实现, length 会自动更新,而对象是键值对
  • 使用对象可以创建伪数组,伪数组可以正常使用数组的大部分方法

相关文章

  • JavaScript之伪数组和数组细谈

    想成为那种不声不响,但是什么都做得很好的人。 对象与数组的关系 在JavaScript中,除了5种原始数据类型之外...

  • JavaScript 数组与伪数组简介

    JavaScript-数组与伪数组简介 本文章面向小白 数组与伪数组的概念 数组与伪数组从何而来在JavaScri...

  • 前端常见面试题(十)

    目录: 1,简述同步和异步的区别 2, 数组去重(手写代码) 3, 在JavaScript中什么是伪数组?如何将伪...

  • 前端常见面试题十七

    目录: 怎样添加、移除、复制、创建、查找节点 在JavaScript中什么是伪数组?如何将伪数组转化为标准数组 j...

  • 原生js面试题(一)

    目录: 怎样添加、移除、复制、创建、查找节点 在JavaScript中什么是伪数组?如何将伪数组转化为标准数组 j...

  • 【IMWeb秋招训练营】【Day3】面试题总结

    经典面试题 9.在Javascript中什么是伪数组?如何将伪数组转化为标准数组? 具有length属性 按索引方...

  • 2018-04-22

    javascript基础 一.函数的arguments 伪数组:像数组,但不是数组 可以动态添加参数 二.函数的其...

  • 伪数组

    1、伪数组特点 2、常见伪数组 3、伪数组与数组的区别 4、伪数组转成真数组

  • 数组和伪数组

    数组和伪数组的区别 伪数组是一个对象(Object),而真实的数组是一个数组(Array)也是对象 拥有lengt...

  • slice方法

    slice方法 实现伪数组转数组:[].slice.call(伪数组)

网友评论

    本文标题:JavaScript之伪数组和数组细谈

    本文链接:https://www.haomeiwen.com/subject/hfybfrtx.html