一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
数组的遍历
1. for 循环
要注意的是:for循环还有一个特别之处,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
2. forEach
- 不对未初始化的值进行任何操作(稀疏数组)
- 没有办法中止或跳出
forEach()循环
3. for...in
- 不应该用于迭代一个关注索引顺序的数组
for...in会往array的原型链上寻找,则遍历的不只是数组内的元素,还有其新增的原型属性和索引。
let arr = [1, 2, 3]
for (let i in arr) {
if (arr[i] > 2) {
console.log('使用for...in循环得到的值:', i)
}
}
// 使用for...in循环得到的值:2
//给数组的原型上增加一个方法
Array.prototype.method = function () {
console.log('this is a method')
}
arr.name = 'zz'
for (let i in arr) {
console.log(i)
}
// 0
// 1
// 2
// name
// method
4. for...of
for...of在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环。
// item是数组元素 无法直接获取索引
for (let item of arr) {
if (item > 2) {
//return item
}
}
那么如何获取索引呢?
- 借用
entries()
let arr = ['a','b','c']
for (let [index, item] of arr.entries()){
console.log(index, item)
}
//0 "a"
//1 "b"
//2 "c"
- 借用
Map结构
先将数组转化为Map
let arr = [ 'a', 'b', 'c' ];
for( let [ index, item ] of new Map( arr.map( ( item, index ) => [ index, item ] ) ) ) {
console.log( index, item );
}
5. findIndex()
返回第一个满足条件的元素下标
console.log(arr.findIndex(function(item){
return item > 2
}))
6. 其他
如every,some,find,像findindex一样,能提前终止循环。
对象的遍历
1. for...in
它以任意顺序迭代一个对象的除[Symbol]以外的可枚举属性,包括继承的可枚举属性。
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性
2. 键值的遍历
- 键值对的遍历
Object.entries()
返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
可以通过数组解构赋值方式访问键和值
const obj = { a: 1, b: 2, c: 3 };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`); // "a 1", "b 2", "c 3"
}
与Map的转换
因为new Map() 构造函数接受一个可迭代的entries。借助Object.entries将Object转换为Map
var obj = { foo: "bar", baz: 42 };
var map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }
- 键的遍历
Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj));
// ['0', '1', '2']
- 值的遍历
Object.values() 方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj));
// ['a', 'b', 'c']
Set 的遍历
1. forEach
使用回调函数进行处理
let set = new Set([1, 2, 3]);
set.forEach((value, key) => console.log(key + ' : ' + value))
2. 键值对
keys(),values(),entries()返回的都是遍历器对象
let set = new Set(['one', 'two', 'three']);
for (let item of set.keys()) {
console.log(item);
}
// one
// two
// three
for (let item of set.values()) {
console.log(item);
}
// one
// two
// three
for (let item of set.entries()) {
console.log(item);
}
// ["one", "one"]
// ["two", "two"]
// ["three", "three"]
Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values()方法。
Set.prototype[Symbol.iterator] === Set.prototype.values // true
这意味着,可以省略values方法,直接用for...of循环遍历 Set。
let set = new Set(['one', 'two', 'three']);
for (let x of set) {
console.log(x);
}
// one
// two
// three
因为扩展运算符使用for...of 循环,所以可以结合扩展运算符使用。
let set = new Set(['red', 'green', 'blue']);
let arr = [...set];
// ['red', 'green', 'blue']
Map 的遍历
1. forEach
map.forEach(function(value, key, map) {
console.log("Key: %s, Value: %s", key, value);
});
2. 键值对
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
总结
- 灵活运用遍历需要掌握的不仅仅是一些上述提到的方法,前提需要掌握的是如
Set和Map的定义,Map和Object的区别等; - 了解一些包括迭代器,扩展运算符的内容,也能掌握数据的转化,如
Map和数组的相互转化,而不需要死记硬背。