伪数组与可迭代对象
这两者都可以通过Array.from(arrayLike[,mapFn[,thisArg]])
来返回一个数组。
伪数组
首先先得清楚对象和数组的差别:
- 对象的原型链上只有Object.prototype,而数组的原型链上有Array.prototype和Object.prototype
- 对象没有length属性,数组有,且自动更新
- 对象根据键值对取值,而数组根据序号取值
ok,接下来就可以引出伪数组了。
定义:
- 拥有length属性,其他属性为非负整数字符串(因为对象使用[]来取值,会将数值隐式转换为字符串)
- 不具有数组具有的方法,即原型链上没有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)
方法有:
- m.get(键)可以得到对应的值
- m.set(键,值)来新添一维数组,如果键名重复的话,覆盖原先的。如果只有一个参数,则值为undefined
- m.has(键)来确定是否存在这个键
- m.delete(键)来删除一维数组成员
Set
Set和数组相对应,他的出现是为了解决数组中重复成员的问题。
创建一个Set。需要提供一个一维数组作为输入,重复的元素在Set中自动被过滤。(注意,他的格式依然是个{}格式,而不是数组格式,格式如下Set { 2323, 23423, 'sfsdfsfs' }
)
方法:
- s.add(值)来添加Set对象成员
- s.delete(值)来删除成员
- s.has(值)
- 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好用