一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情。
对象遍历
ES6 一共有 5 种方法可以遍历对象的属性。
(1)for...in
for...in
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
示例:
const obj = {10:10, b:'bb', 2:2, a:'aa'}
for(let key in obj){
console.log(key, obj[key])
}
// 2 2 10 1 b bb a aa
(2)Object.keys(obj)
Object.keys
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
const obj = {10:10, b:'bb', 2:2, a:'aa'}
console.log(Object.keys(obj))
// ["2", "10", "b", "a"]
(3)Object.entries()
Object.entries()
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
(4)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
const obj = {10:1, b:'bb', 2:2, a:'aa'}
console.log(Object.getOwnPropertyNames(obj))
// ["2", "10", "a", "b"]
(5)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols
返回一个数组,包含对象自身的所有 Symbol 属性的键名。
const obj = {10:1, b:'bb', [Symbol('1')]: 1}
console.log(Object.getOwnPropertySymbols(obj))
// [Symbol(1)]
(6)Reflect.ownKeys(obj)
Reflect.ownKeys
返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
- 首先遍历所有数值键,按照数值升序排列。
- 其次遍历所有字符串键,按照加入时间升序排列。
- 最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
上面代码中,
Reflect.ownKeys
方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性2和10,其次是字符串属性b和a,最后是Symbol
属性。
数组遍历
(1)for循环
for(let i=0; i< arr.length; i++){
// ...
}
在这种循环方式中,循环每进行一次,就要检查一下数组长度。读取属性(数组长度)要比读局部变量慢,尤其是当 array
里存放的都是 DOM
元素,因为每次读取都会扫描一遍页面上的选择器相关元素,速度会大大降低。所以可以将arr.length存到局部变量中进行优化:
let len = arr.length
for(let i=0; i< len; i++){
// ...
}
(2)for ... in循环
for(let i in arr){
console.log(i, arr[i])
}
for-in
需要分析出array
的每个属性,这个操作性能开销很大。用在 key
已知的数组上是非常不划算的。所以尽量不要用for-in
,除非你不清楚要处理哪些属性,例如 JSON
对象这样的情况
(3)for ... of 循环
for of只能遍历数组不能遍历对象
for(let val in arr){
console.log(val)
}
(4)Array.forEach(callback)
forEach()
方法为每个数组元素调用一次函数(回调函数)。回调可以接收3个参数:元素,索引,数组本身
示例:
const arr = ['a', 2, 10, 'b']
arr.forEach(function(item, index, ar){
console.log(item, index, ar)
})
// a 0 ["a", 2, 10, "b"]
// 2 1 ["a", 2, 10, "b"]
// 10 2 ["a", 2, 10, "b"]
// b 3 ["a", 2, 10, "b"]
效率速度:for > for-of > forEach > for-in
(5)Array.map(callback)
map()
可以通过return返回一个新数组,不改变原来数组,回调可以接收3个参数:元素,索引,数组本身
const arr = ['a', 2, 10, 'b']
const newArr = arr.map(function(item, index, ar){
return item + '1'
})
console.log(arr, newArr)
// arr: ["a", 2, 10, "b"]
// newArr: ["a1", "21", "101", "b1"]
(6)Array.filter()
filter() 方法创建一个包含通过测试的数组元素的新数组。常做条件过滤使用。
const arr = [8, 2, 10, 4]
const newArr = arr.filter(function(item, index, ar){
return item > 5
})
console.log(newArr)
// [8, 10]
(7)Array.reduce()
reduce()
方法在每个数组元素上运行函数,以生成(减少它)单个值。reduce()
方法不会减少原始数组。此函数回调接受 4 个参数:总数(初始值/先前返回的值)、当前元素、索引、数组本身
var arr = [45, 4, 9, 16, 25];
var sum = arr.reduce(myFunction);
function myFunction(total, value, index, array) {
return total + value;
}
console.log(sum) // 99
console.log(arr) // [45, 4, 9, 16, 25]
(8)Array.reduceRight()
reduceRight
和reduce
用法一样,唯一区别是reduce
遍历是从左到右遍历元素。reduceRight
是从右到左。
(9)Array.every()
every() 方法检查所有数组每个元素值是否通过测试/条件判断。返回值为true或false
var arr = [45, 4, 9, 16, 25];
var res = arr.every(function (value, index, array) {
return value > 18;
});
console.log(res) // false
var arr1 = ['abc', 'apple', 'aha'];
var res1 = arr.every(function (item, index, array) {
return item.indexOf('a')>-1;
});
console.log(res1) // true
(10)Array.some()
some() 方法检查所有数组是否有元素值通过测试/条件判断。有一个元素满足条件则返回值为true。每个值都不满足则为false
var arr = [45, 4, 9, 16, 25];
var res = arr.some(function (value, index, array) {
return value > 18;
});
console.log(res) // true