GG资源网

JavaScript遍历对象及数组方法小结(JS遍历对象有几种方法)

JavaScript遍历对象及数组方法小结

1、for...in 语句


1.1 遍历对象属性名称

for...in 语句常用于遍历特定对象的属性,包括字段名称属性及函数名称属性。在JavaScript语言中,它们均称为属性 (property)。

let obj = {
name: 'obj',

showName() {
console.log(this.name);
}
};

for (const propName in obj) {
console.log(propName, typeof(obj[propName]));
}

显示:

name – "string"
showName – "function"

利用这一点,可方便地查看特定对象的所有属性或方法名称。下面语句打印出console对象所有的属性:

for (const propName in console) {
console.log(propName, typeof(console[propName]));
}

显示:

debug – "function"
error – "function"
log – "function"
info – "function"
warn – "function"
clear – "function"
...

可以看出,这些属性全部均是console的函数名称,因为console没有属性名称。

1.2 遍历数组索引值

for...in 用于数组中,则遍历数组索引值。

let array = ['a', 'b', 'c'];

for (const index in array) {
console.log(index, array[index]);
}

显示:

0 – "a"
1 – "b"
2 – "c"

1.3 遍历字符串索引值

由于字符串是由字符组成的数组,因此 for...in 也可用于遍历字符串的索引值。

let str = "abc";

for (const index in str) {
console.log(index, str[index]);
}

显示:

0 – "a"
1 – "b"
2 – "c"

2、for...of 语句


for...of 语句用于遍历可遍历对象 (iterable objects)的元素。这些可遍历对象包括字符串、数组、以及类似于数组的对象,这些对象都带有length属性。

2.1 不能用于遍历对象属性名称

for...of 语句不能用于遍历对象的属性名称。因此,下面的代码是错误的:

let obj = {
name: 'obj',

showName() {
console.log(this.name);
}
};

for (const propName of obj) {
console.log(propName);
}

显示:

TypeError: undefined is not a function (near '...propName of obj...')

意为,将 for...of 语句用于对象上面,无法提取具体的数值。

2.2 遍历数组元素

for...of 语句经常用于遍历数组中各元素的数值。

let arr = [2, 4, 6, 8, 10];

for (const value of arr) {
console.log(value);
}

显示:

2
4
6
8
10

2.3 遍历字符串中的字符

由于字符串是由字符组成的数组,因此 for...of 也可用于遍历字符串的字符。

let str = "abc";

for (const letter of str) {
console.log(letter);
}

显示:

a
b
c

2.4 解包

数组元素如果是带有特定属性名称的对象,可利用解包性质来快速遍历这些属性值。看下面例子。

function Point(x, y) {
return {x:x, y:y};
}

let points = [Point(1, 2), Point(2, 3), Point(4, 5)];

for (const point of points) {
console.log(point.x, point.y);
}

可将Point视为一个构造器 (constructor),每次调用Point(x, y)都会创建并返回该类的一个对象,且含有x及y的属性名称。points则是一个含有多个Point对象的数组。上面的代码遍历出每个Point对象后,赋值于point变量,然后打印出它们的x值及y值。

如果我们不希望每次都通过引用对象属性的方式来访问x及y值,则可编写代码如下:

for (const point of points) {
let x = point.x;
let y = point.y;
console.log(x, y);
}

这一步可利用ES6的const解包特性予以简化:

for (const point of points) {
const {x, y} = point;
console.log(x, y);
}

更进一步,我们可以直接解包:

for (const {x, y} of points) {
console.log(x, y);
}

2.5 遍历Map

let scoreMap = new Map([
['Mike', 75],
['Tom', 80],
['Smith', 90]
]);

for (const [key, value] of scoreMap) {
console.log(key, value);
}

与上一节不同的是,Map需要使用 [key, value] 的方式来解包。

3、forEach 方法


3.1 forEach 常见调用方式

for...in,for...of 均是语句,与它们不同的是,forEach是数组的内嵌方法。这意味着我们可以直接在数组对象上面直接调用该方法。

let arr = [1, 3, 5, 7, 9];

arr.forEach((element) => {
console.log(element);
});

作为数组方法,forEach有一个参数,该参数的类型是函数,称为回调函数 (callback function)。所谓回调函数,是指一旦程序员提供了这样的函数,JavaScript引擎将负责调用此函数。

回调函数的价值在于回调函数可能存在多个参数,而这些参数将由JavaScript引擎自动提供。在回调函数中,我们可对JavaScript引擎所自动提供的参数进行进一步加工。

在上面的回调函数中,element是由JavaScript引擎自动提供的,代表每个数组元素。

上面的代码采用了lambda匿名表达式。它等同于:

let arr = [1, 3, 5, 7, 9];

function callback(element) {
console.log(element);
}

arr.forEach(callback);

可见,lambda表达式更加简练。

3.2 forEach 的参数

forEach共有3个参数 (上面例子只用了第1个),它们的排列顺序如下:

arr.forEach((element, index, array) => {
console.log(element);
console.log(index);
console.log(array);
});

参数element是数组元素,参数index是数组元素所在数组中的索引值,参数array是整个数组。

一般情况下,我们仅需用到element及index参数就足够了。由于是每次迭代,因此,forEach方法中的array参数较少用到。

index每次遍历时都会加1,且每次都会与array的长度比较。一旦超出array的界限,就会终止遍历。如果遍历过程中,修改了array的长度,则需特别注意这一点。

3.2 forEach 遍历的终止

如何中止forEach的遍历?JavaScript并未提供这样的机制,但我们可以用一个双重嵌套的异常来终止遍历。

let arr = [1, 3, 5, 7, 9];

try {
arr.forEach((element, index, array) => {
try {
console.log(index);
if (index >= 3) {
throw new Error('forEach termination signal');
}
} catch (error) {
throw error;
}
});
} catch (e) {
if (e.message === 'forEach termination signal') {
console.log('forEach terminated.');
}
}

console.log('This line of code should be executed.');

显示:

0
1
2
3
forEach terminated.
This line of code should be executed.

我们设定,当index的值大于等于3时,需要终止遍历。这样,在第7行,当此条件满足时,即抛出"forEach termination signal"的异常。

此时,程序流程转入到第10行至第12行最内层的异常捕获处理代码:

} catch (error) {
throw error;
}

捕获异常后,如果我们不重新抛出异常,JavaScript引擎则会认为我们已正确地处理了异常,因此会恢复中断的遍历进程,继续处理下一个数组元素,这不是我们想要的。因此,我们在此重新抛出该异常,以切实终止遍历。

这时,forEach的遍历因异常而终止,从而达到了我们的最初的目标。但因为有异常,如果我们未作任何处理,则该异常会导致整个程序都终止运行。只有在我们处理了异常后,程序才能往下走。这就是第14行至18行最外层异常捕获代码的作用:

} catch (e) {
if (e.message === 'forEach termination signal') {
console.log('forEach terminated');
}
}

先判断它是不是"forEach termination signal"。如果是,则简单地打印一行消息。由于这里未再抛出新的异常,因此JavaScript引擎认为我们已经正确地处理了异常,则继续执行后面的代码。这样,最后一行第20行语句将被执行并打印出"This line of code should be executed."的文本。

一般来讲,如果我们需要在数组的遍历过程中终止遍历,不要使用 forEach 语句,使用最传统的方式即可:

let arr = [1, 3, 5, 7, 9];

for (let i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
if (i >= 3) {
break;
}
}

console.log('This line of code should be executed.');

这样即可在遍历中访问数组的索引值与数组元素,又可以极为方便地随时终止遍历。

JS遍历对象有几种方法

几天前一个小伙伴问我Object.getOwnPropertyNames()是干什么用的

平时还真没有使用到这个方法,一时不知如何回答

从方法名称来分析,应该是返回的是对象自身属性名组成的数组

那和Object.keys()方法不就一样了吗

感觉事情并不这么简单,于是我仔细看了一下这几种遍历对象的方法的区别

for in

for in 循环是最基础的遍历对象的方式,它还会得到对象原型链上的属性

// 创建一个对象并指定其原型,bar 为原型上的属性

const obj = Object.create({

bar: \'bar\'

})

// foo 为对象自身的属性

obj.foo = \'foo\'

for (let key in obj) {

console.log(obj[key]) // foo, bar

}

可以看到对象原型上的属性也被循环出来了

在这种情况下可以使用对象的hasOwnProperty()方法过滤掉原型链上的属性

for (let key in obj) {

if (obj.hasOwnProperty(key)) {

console.log(obj[key]) // foo

}

}

这时候原型上的 bar 属性就被过滤掉了

Object.keys

Object.keys()是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,它会自动过滤掉原型链上的属性,然后可以通过数组的forEach()方法来遍历

Object.keys(obj).forEach((key) => {

console.log(obj[key]) // foo

})

另外还有Object.values()方法和Object.entries()方法,这两方法的作用范围和Object.keys()方法类似,因此不再说明

for in 循环和Object.keys()方法都不会返回对象的不可枚举属性

如果需要遍历不可枚举的属性,就要用到前面提到的Object.getOwnPropertyNames()方法了

Object.getOwnPropertyNames

Object.getOwnPropertyNames()也是 ES5 新增的一个对象方法,该方法返回对象自身属性名组成的数组,包括不可枚举的属性,也可以通过数组的forEach方法来遍历

// 创建一个对象并指定其原型,bar 为原型上的属性

// baz 为对象自身的属性并且不可枚举

const obj = Object.create({

bar: \'bar\'

}, {

baz: {

value: \'baz\',

enumerable: false

}

})

obj.foo = \'foo\'

// 不包括不可枚举的 baz 属性

Object.keys(obj).forEach((key) => {

console.log(obj[key]) // foo

})

// 包括不可枚举的 baz 属性

Object.getOwnPropertyNames(obj).forEach((key) => {

console.log(obj[key]) // baz, foo

})

ES2015 新增了 Symbol 数据类型,该类型可以作为对象的键,针对该类型 ES2015 同样新增了Object.getOwnPropertySymbols()方法

Object.getOwnPropertySymbols

Object.getOwnPropertySymbols()方法返回对象自身的 Symbol 属性组成的数组,不包括字符串属性

Object.getOwnPropertySymbols(obj).forEach((key) => {

console.log(obj[key])

})

什么都没有,因为该对象还没有 Symbol 属性

// 给对象添加一个不可枚举的 Symbol 属性

Object.defineProperties(obj, {

[Symbol(\'baz\')]: {

value: \'Symbol baz\',

enumerable: false

}

})

// 给对象添加一个可枚举的 Symbol 属性

obj[Symbol(\'foo\')] = \'Symbol foo\'

Object.getOwnPropertySymbols(obj).forEach((key) => {

console.log(obj[key]) // Symbol baz, Symbol foo

})

Reflect.ownKeys

Reflect.ownKeys()方法是 ES2015 新增的静态方法,该方法返回对象自身所有属性名组成的数组,包括不可枚举的属性和 Symbol 属性

Reflect.ownKeys(obj).forEach((key) => {

console.log(obj[key]) // baz, foo, Symbol baz, Symbol foo

})

对比

JS遍历对象有几种方法 (https://www.wpmee.com/) javascript教程 第1张

结论

这其中只有 for in 循环会得到对象原型链上的属性,其它方法都只适用于对象自身的属性

ES 语言后续添加的新特性不会对以前的代码产生副作用,比如在 ES2015 之前就存在的 for in 循环,Object.keys() 和 Object.getOwnPropertyNames() 是肯定不会返回 Symbol 属性的。

以上就是JS遍历对象有几种方法的详细内容,更多请关注网站的其它相关文章!

由于网站搬家,部分链接失效,如无法下载,请联系站长!谢谢支持!
1. 带 [亲测] 说明源码已经被站长亲测过!
2. 下载后的源码请在24小时内删除,仅供学习用途!
3. 分享目的仅供大家学习和交流,请不要用于商业用途!
4. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
5. 本站所有资源来源于站长上传和网络,如有侵权请邮件联系站长!
6. 没带 [亲测] 代表站长时间紧促,站长会保持每天更新 [亲测] 源码 !
7. 盗版ripro用户购买ripro美化无担保,若设置不成功/不生效我们不支持退款!
8. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
9. 如果你也有好源码或者教程,可以到审核区发布,分享有金币奖励和额外收入!
10.如果您购买了某个产品,而我们还没来得及更新,请联系站长或留言催更,谢谢理解 !
GG资源网 » JavaScript遍历对象及数组方法小结(JS遍历对象有几种方法)

发表回复

CAPTCHAis initialing...