伪数组与可迭代对象

Posted caiyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了伪数组与可迭代对象相关的知识,希望对你有一定的参考价值。

这两者都可以通过Array.from(arrayLike[,mapFn[,thisArg]])来返回一个数组。

伪数组

首先先得清楚对象和数组的差别:

  1. 对象的原型链上只有Object.prototype,而数组的原型链上有Array.prototype和Object.prototype
  2. 对象没有length属性,数组有,且自动更新
  3. 对象根据键值对取值,而数组根据序号取值

ok,接下来就可以引出伪数组了。

定义:

  1. 拥有length属性,其他属性为非负整数字符串(因为对象使用[]来取值,会将数值隐式转换为字符串)
  2. 不具有数组具有的方法,即原型链上没有Array.prototype

内容如下:

var fakeArray = {
    length: 3,
    "0": "first",
    "1": "second",
    "2": "third"
};

伪数组是个对象(所以没有Array.prototype的属性值),但他和数组一样拥有length,数值属性下标,从外观上看伪数组,看不出他和数组的区别。

伪数组的意义就是:让普通对象也可以正常使用数组的很多方法。

大名鼎鼎的伪数组有:arguments对象,DOM的childNodes。

我们通过Array.isArray()来判断其是否为数组。

可迭代对象

在学习可迭代对象之前,我们先来学习ES6新引入的Map和Set数据类型。

Map

Map相对应的是Object对象,两者都是键值对结构。(注意,他的格式依然是{}格式,而不是数组格式,格式如下Map { 2323 => 23423, ‘sdfasdf‘ => 234234, 324 => ‘sfsdfas‘ }

但是Object对象有一个小问题,即Object的键必须得是字符串,但实际上Number或者其他数据类型作为键也是十分合理的。

为了解决这个问题,最新的ES6引入了新的数据类型Map。

Map通过一个二维数组来定义。

var m = new Map([[100,‘sdfsd‘],[35,‘dsfdsf‘]]),其中每个数组中的第一个是键,第二个是值

但是,注意,要想获得Map的值不能像对象一样直接访问,需要使用set来添加键值对,通过get来得到值(通过has来判断是否有这个key)

方法有:

  1. m.get(键)可以得到对应的值
  2. m.set(键,值)来新添一维数组,如果键名重复的话,覆盖原先的。如果只有一个参数,则值为undefined
  3. m.has(键)来确定是否存在这个键
  4. m.delete(键)来删除一维数组成员

Set

Set和数组相对应,他的出现是为了解决数组中重复成员的问题。

创建一个Set。需要提供一个一维数组作为输入,重复的元素在Set中自动被过滤。(注意,他的格式依然是个{}格式,而不是数组格式,格式如下Set { 2323, 23423, ‘sfsdfsfs‘ })

方法:

  1. s.add(值)来添加Set对象成员
  2. s.delete(值)来删除成员
  3. s.has(值)
  4. Set无法单独取成员,因为其既没有下标,又没有键值对,所以没有办法取到单个成员

iterable

Map,Set,Array的作用是一致的,都是为了保存一组数据,所以这三者都属于iterable类型(因为数据都是迭代存储的,所以存储在迭代器中)。而我们往往会有这么一个需求:遍历这一组数据。

Array可以使用for循环遍历,但是因为Set,Map没有下标,所以无法使用for循环遍历。

所以,我们创建了一个新的方法:for..of来遍历,for..of着眼的不再是下标,而是每个迭代对象,Array的迭代对象是单值,Map的迭代对象是一维数组,Set的迭代对象也是单值。

切记,for..in不能用于迭代内容,他仅能用于Array的迭代下标及Object的迭代属性,而Map,Set都是不能使用这个for..in,能且仅能使用for..of。

然而,更好的方式是直接使用iterable内置的forEach()方法,他接受一个函数,每次迭代就自动回调该函数。

Array:

var a = ['A', 'B', 'C'];
a.forEach(function(element,index,array){//第一个参数是当前元素的值,第二个参数是当前索引,第三个参数指向Array对象本身
    
    console.log(element)
    console.log(index)
    console.log(array)
    

})

Map:

var m = new Map([[2323,23423],['sdfasdf',234234],[324,'sfsdfas']])

m.forEach(function(value,key,map){//第一个参数是当前数组的值,第二个参数当前数组的键,第三个指向Map对象本身
    console.log(value)
    console.log(key)
    console.log(map)

})

Set:

var m = new Set([2323,23423,'sfsdfsfs'])
console.log(m)
m.forEach(function(element,sameElement,Set){//第一个是当前元素的值,第二个也是当前元素的值,第三个是指向Set对象本身
    console.log(element)
    console.log(sameElement)
    console.log(Set)

})

记忆技巧:

for(var i=0;i<9;i++):仅能用于Array及伪数组。因为这个方法要求有length属性及下标,只有Array和伪数组有

for..in:仅能用于Array,Object,结果是迭代属性(for (var item in Array))

for..of:仅能用于Array,Map,Set。这个方法是迭代器的专属,而只有这三者是迭代器,Object不是迭代器,结果是迭代内容(for(var item of Set))

forEach(function):是迭代器的方法,因为参数的丰富性,所以比for..of好用

以上是关于伪数组与可迭代对象的主要内容,如果未能解决你的问题,请参考以下文章

python 迭代器与可迭代对象

仅当特定密钥对值与可迭代匹配时,才在 JSON 对象中获取多个 JSON 密钥对值

如何在UL中迭代使用appendChild和片段LI?

数组拓展方法

数组拓展方法

3. 有点难~ Python函数式编程中 itertools 模块