for循环
- 只用于遍历数组,书写麻烦
let arr = ['a', 'b', 'c']
for (let i = 0,len = arr.length;i < len;i++) {
console.log(i)
}
forEach循环
- 数组内置方法,不能中途跳出循环,break(
SyntaxError: Illegal break statement
)和return都无效
let arr = ['a', 'b', 'c']
arr.forEach(item => {
console.log(item)
})
- map与forEach的区别
- 用法:forEach返回值为undefined;map返回值为一个新数组
- 定义:forEach针对每一个元素执行提供的函数;map创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来。
- forEach 不会直接改变调用它的对象,但是那个对象可能会被 callback 函数改变
- 从功能上没有差别可以相互替换,但适用场景不同
for...in
- 遍历对象(数组也是对象)及其原型链中可枚举属性
(Object.keys(obj)
仅遍历对象自身,不遍历原型链) - 遍历键名,为字符串类型(遍历数组时为数组下标,返回仍为字符串类型)
- 对象的键名存为数字字符串时会出现顺序不一致,原因在于for...in遍历顺序为:**先按照升序遍历出整数属性,然后其他属性按照创建时候的顺序遍历出来。**所谓整数属性,即
String(Math.trunc(Number(prop)) === prop
,Math.trunc
去除小数部分参考链接,负数的话当作字符串处理.....
Array.prototype.getLength = function() {
return this.length;
};
var arr = ['a', 'b', 'c'];
arr.name = 'June';
Object.defineProperty(arr, 'age', {
enumerable: true,
value: 17,
writable: true,
configurable: true
});
console.log(Object.keys(arr)) // ["0", "1", "2", "name", "age"]
for(var i in arr) {
console.log(typeof(i)) // string string string string string string
console.log(i); // 0,1,2,name,age,getLength
}
let codes = {
"49": "Germany",
"41": "Switzerland",
"44": "Great Britain",
"1": "USA"
};
for(let code in codes) {
console.log(code); // 1, 41, 44, 49
}
不推荐在数组中使用for...in遍历
for..of
- 修复了forEach和for...of的缺点同时提供了所有数据结构的统一操作接口
- 遍历值为键值,通过
Object.keys() Object.entries()
来获取索引 - 不支持遍历普通对象
Uncaught TypeError: obj is not iterable
普通对象没有迭代器
数组空项:
['a',,'c']
只有 forEach 和 for...in 遍历会跳过空值,其他会解析为 undefined,因此建议使用for...of 或for循环,因为JSON.parse('["a", , "c"]')
会报错
在写javascript中的遍历这篇时深冻结用到的Object.getOwnPropertyNames()
,然后又把遍历看了一遍,整理一下,发现之前写的这篇不够细.来补充下
对象遍历
- Object.getOwnPropertyNames(obj) 对象自身 除Symbol之外的 可枚举+不可枚举属性 的数组
- **Object.getOwnPropertySymbols(obj)**对象自身 Symbol 属性的数组
- **Object.keys()**对象自身 除Symbol之外的 可枚举属性 (非对象参数会被转为对象)
- for...in对象自身+继承 除Symbol之外的 可枚举属性
- **Reflect.ownKeys()**对象自身 所有属性(可枚举+不可枚举,非Symbol+Symbol),参数不是对象会报错
TypeError
等同于Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。
// 对象自身 可枚举 字符类型 name
// 对象自身 不可枚举 字符类型 age
// 对象自身 可枚举 Symbol类型
// 对象自身 不可枚举 Symbol类型
// 原型对象 可枚举 字符类型 protoProperty
// 原型对象 可枚举 Symbol类型 protosymbolproperty
// 原型对象 不可枚举 字符类型 protoUnenmerProto
// 原型对象 不可枚举 Symbol类型
// obj对象属性定义
var obj = { 'name': 'Poly'}
obj[Symbol()] = 'objsymbolproperty'
Object.defineProperty(obj, 'age', { value: '18', enumerable: false })
Object.defineProperty(obj, Symbol(), { value: 'symbol', enumerable: false })
// 原型对象属性定义
Object.prototype.protoProperty = 2
Object.prototype[Symbol()] = 'protosymbolproperty'
Object.defineProperty(Object.prototype, 'protoUnenmerProto', { value: 'protoUnenmerProto', enumerable: false })
Object.defineProperty(Object.prototype, Symbol(), { value: 'protosymbol', enumerable: false })
// 不同的遍历方法
console.log('Object.getOwnPropertyNames')
console.log(Object.getOwnPropertyNames(obj)) // ["name", "age"]
console.log('Object.getOwnPropertySymbols')
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(), Symbol()]
console.log('Reflect.ownKeys')
console.log(Reflect.ownKeys(obj)) // ["name", "age", Symbol(), Symbol()]
console.log("For in")
for (var a in obj) {
console.log(a) // name protoProperty
}
console.log('Object.keys')
console.log(Object.keys(obj)) // ["name"]
// 报错 因为对象没有Iterator接口
console.log('For of')
for (var a of obj) {
console.log(a)
}
// 顺序
// 数字类型|数字字符串类型 (数字升序) > 字符串类型,Symbol类型(插入顺序)
var test = {'45': 45, '0': 0, 2: 2, '-2': '-2'} // undefined
test // {0: 0, 2: 2, 45: 45, -2: "-2"}
总结:
Object
的静态方法遍历的都只是对象自身的属性!
数组遍历
- for循环
使用无语句的
for
一定要使用分号 如果没有分号,循环声明之后的行将被视为循环语句。很坑的分号与for循环的问题哈哈 - forEach
- 无法中断,break和return都无法中断
forEach()
不会在迭代之前创建数组的副本- promise 或 async会存在问题??
- For...in 遍历的是属性名,数组是特殊的对象
- For...of 遍历的是属性值
var arr = ['0','1', ,'3', undefined, null, 6, '', 8]
console.log('for循环')
for (let i = 0;i < arr.length;i++) {
console.log(arr[i]) // 0 1 undefined 3 undefined null 6 8
}
console.log('forEach')
arr.forEach((item, index) => {
console.log(item) // // 0 1 3 undefined null 6 8
})
console.log('for in')
for(let index in arr) {
console.log(arr[index]) // 0 1 3 undefined null 6 8
}
console.log('for of')
for(let item of arr) {
console.log(item) // 0 1 undefined 3 undefined null 6 8
}
总结:
forEach
,for...in
会跳过无效项
遍历中断
- forEach
Uncaught SyntaxError: Illegal break statement
语法报错不能退出循环 - for循环,for...in,for...of可以退出,按预期执行
遍历值
- for循环和for...in遍历键名即key,数组中更习惯称为index
- for...of遍历键值即value
- forEach遍历的回调函数第一项是键值value,第二项是键名index
for..of..循环扩展
实际上是依次将迭代器(或任何可迭代的对象,如生成器函数)的值赋予指定变量并进行循环的语法,当对象没有默认迭代器的时候,当然不可以进行循环,而通过给对象增加一个默认迭代器,即[Symbol.iterator]
属性,就可以实现for..of..循环,实际上是依次将迭代器(或任何可迭代的对象,如生成器函数)的值赋予指定变量并进行循环的语法,当对象没有默认迭代器的时候,当然不可以进行循环,而通过给对象增加一个默认迭代器,即[Symbol.iterator]
属性,就可以实现
Object.prototype[Symbol.iterator] = function *keys(){
for(let n of Object.keys(this)){ // 此处使用Object.keys获取可枚举的所有属性
yield n
}
}
最后给自己挖个坑,vue
的v-for
的源码