数组遍历
1. arr.forEach(callback(currentVal [, index [,array]] ) [,thisArg] )
- callback含有三个参数: 当前值、当前索引、目标数组
- thisArg — callback中的this指向
- return false;终止本次循环,继续下一个;
- 抛出异常;可以跳出整个循环
遍历数组中的所有值并忽略回调函数的返回值。
2.arr.every(...)
如果有一个不满足条件,中止循环,直接返回false; 全部满足返回true;
3.arr.some(...)
如果有一个满足条件,中止循环,直接返回true; 全部不满足返回false;
4.for...in
遍历的是数组的下标(索引)以及自定义的可枚举属性。
var obj = {a: 2, b: 4};
for(var k in obj){
console.log(obj[k])
}
数组使用for...in
遍历时的缺点:
(1) 数组的键名是数字,但是for...in
循环是以字符串作为键名“0”、“1”、“2”等等。
(2)for...in
循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
(3) 某些情况下,for...in
循环会以任意顺序遍历键名。
所以for...in
主要适用于对象
5. for循环
遍历数组的下标值
6. for...of
(ES6新增)
遍历数组的值。
let arr = [1,2,3];
arr.foo = "hello";
for(let i of arr){
console.log(i) // 1,2,3 数组的遍历器接口只返回具有数字索引的属性,不会返回数组的foo属性
}
// for...in 遍历的是数组的所有可枚举属性
for(let index in arr){
console.log(index) // 0,1,2,foo
}
原理:for...of
首先会向目标对象请求一个迭代器对象(遍历器对象),调用迭代器对象的next()方法来遍历所有返回值。
意味着for...of
的目标对象必须具有Iterator接口
,JS中具有Iterator接口
的数据结构:数组(Array)、类数组对象(函数中的arguments 、DOM NodeList 对象)、String、Map和Set结构 、 Generator 对象
。
数组有内置的@@iterator
,我们使用内置的@@iterator
来手动遍历数组,看看是如何工作的?
var arr = ["zhangsan","lisi","wangwu","h"];
for(let val of arr){
console.log(val) //依次打印出值
}
var _iterator = arr[Symbol.iterator](); // _iterator即为迭代器对象
console.log(_iterator.next()) // {"value":"zhangsan","done":false}
console.log(_iterator.next()) // {"value":"lisi","done":false}
console.log(_iterator.next()) // {"value":"wangwu","done":false}
console.log(_iterator.next()) // {"value":"h","done":false}
console.log(_iterator.next()) // {"done":true}
如果一个自定义对象不在上述结构中,想使用for..of
,那么可以为对象手动添加Iterator接口
,直白讲就是添加Symbol.iterator属性
,返回一个迭代器对象(就是for...of访问的),对象中要有一个next()
方法,返回一个具有value和done属性的对象{value: ...,done:...}
。
{
let myObj = {
data: ["zhangsan","lisi"],
[Symbol.iterator]() {
let index = 0;
let next = function() {
if(index < this.data.length){
return {value: this.data[index++], done: false }
}
return { value: undefined, done: true}
}
// 返回迭代器对象(遍历器对象)
return {
// 必须具有next() 方法
next: next.bind(this)
}
}
}
for(let val of myObj){
console.log(val) // “zhangsan” “lisi”
}
}
可通过ES6中 Generator生成器
快速创建iterator接口
总结:for...of
相对于上面那些,具备的优点:
(1) 有着同for...in
一样的简洁语法,但是没有for...in
那些缺点。
(2) 不同用于forEach
方法,它可以与break、continue
和return
配合使用。
(3)提供了遍历所有数据结构的统一操作接口。
对象遍历
1. for...in
遍历对象的所有可枚举属性 (包含原型链)
2. Object.keys(obj)
返回数组,包含对象的所有可枚举属性 (不包含原型链)
3. Object.getOwnPropertyNames(...)
返回数组,包含对象的所有属性,无论是否可枚举。(不包含原型链)
扩展:
(1)in
操作符和 hasOwnProperty()
检查对象中是否包含某个属性。
无论属性是否枚举,只要存在,都会返回true
。区别只在于是否查找原型链
。
// in 操作符 会检查属性名称是否存在对象及其原型链中
console.log("b" in myObj) // true
console.log("c" in myObj) // false
// hasOwnProperty(...)只会检查属性名称是否在对象自身上
myObj.hasOwnProperty("c") // false
(2)obj.propertyIsEnumerable(prop)
检查属性prop是否可枚举(不包含原型链)
// 检查属性是否存在于对象中(而不是在原型链上),并满足enumerable: true
obj.propertyIsEnumerable(prop); // true || false