1. for…in 、for…of
for...in
循环读取键名,(遍历对象)for...of
循环读取键值,(遍历带有iterator接口的Set,Map,String,Array)如果要通过for...of
循环,获取数组的索引,可以借助数组实例的entries
方法和keys
方法。
let list = [4, 5, 6];for (let i in list) {console.log(i + '-' + list[i]); // 打印: 0-4,1-5,2-6}for (let i of list) {console.log(i); // 打印: 4,5,6}
for…in循环
数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。某些情况下,for…in循环会以任意顺序遍历键名。for…in循环主要是为遍历对象而设计的,不适用于遍历数组。for…of循环
有着同for…in一样的简洁语法,但是没有for…in那些缺点。不同于forEach方法,它可以与break、continue和return配合使用。for of 不能遍历对象,只能遍历带有iterator接口的,例如Set,Map,String,Array。2. forEach()
forEach()
: 对数组的每个元素执行一次给定的函数。
返回undefined,不会返回新的数组,只是针对每个元素调用提供的函数循环数组,在原数组的基础上改变数组,可以用于数组的修改。和for的用法一样的。不能用return终止循环,数组还会循环下去。即一旦启动,不能终止循环
let arr= [44, 555, 6666];arr.forEach((val, idx, array) => {console.log(val);// val: 当前值console.log(idx);// idx:当前下标console.log(array);// array: 当前数组});
结果:
440[ 44, 555, 6666 ]5551[ 44, 555, 6666 ]66662[ 44, 555, 6666 ]
forEach() 不会返回新的数组,而是在原数组的基础上改变数组,可以用于数组的修改。
let a = [1, 2, 3, 4, 5, 6];a.forEach((num, index, a) => {// 三个参数分别为:子元素,索引,原数组a[index] = num + 1;})console.log(a) // [2,3,4,5,6,7]
forEach无法直接遍历{}大括号括起来的对象
,此时应使用for循环遍历,或者采用Object.keys
遍历对象的属性。
Object.keys()
方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名
,且只返回可枚举的属性。
//传入对象, 返回 包含对象可枚举属性和方法的数组let obj = {'name': 'xiaoming', 'age': 18};console.log(Object.keys(obj)); // ["name","age"]//传入数组,返回索引值var arr = ["a", "b", "c"];console.log(Object.keys(arr)); //["0", "1", "2"]//传入json对象,获取 属性与值const json = {name: '张三', age: 18 }Object.keys(json).forEach(key => {console.info(key + ':', json[key]); // name:,张三 age:,18})
Object.values()
方法返回一个给定对象自身的所有可枚举属性值
的数组,值的顺序与使用for...in
循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )
var obj = {foo: 'bar', baz: 42 };console.log(Object.values(obj)); // ['bar', 42]// array like objectvar obj = {0: 'a', 1: 'b', 2: 'c' };console.log(Object.values(obj)); // ['a', 'b', 'c']// array like object with random key ordering// when we use numeric keys, the value returned in a numerical order according to the keysvar an_obj = {100: 'a', 2: 'b', 7: 'c' };console.log(Object.values(an_obj)); // ['b', 'c', 'a']// getFoo is property which isn't enumerablevar my_obj = Object.create({}, {getFoo: {value: function() {return this.foo; } } });my_obj.foo = 'bar';console.log(Object.values(my_obj)); // ['bar']// non-object argument will be coerced to an objectconsole.log(Object.values('foo')); // ['f', 'o', 'o']
3. filter()
filter()
: 筛选条件,不改变原数组,返回一个符合函数条件的元素的新数组。
新数组和原来的数组长度不一定一样。
let a = [1, 2, 3, 4, 5, 6];let b = a.filter((num, index, a) => {// b 为一个新的数组return num > 3;})console.log(b); //[4,5,6]
4. map()
map()
: 不改变原数组,返回一个新数组,每个元素为调用函数的结果。
新数组的长度和原来的是一样的,他只不过是逐一对原来数据里的每个元素进行操作。
(而foreach改变原数组,且没有返回值)
map()和 foreach() 不同在于他是有return 的,并且他会返回一个新数组。
let a = [1, 2, 3];let b = a.map(function (n) {return n + 1; }); console.log(a); // [1, 2, 3] 原数组并未改变console.log(b); // [2, 3, 4]
map方法接受一个函数作为参数。该函数调用时,map方法向它传入三个参数:当前成员、当前位置和数组本身。
[1, 2, 3].map(function(elem, index, arr) {return elem * index; // [0, 2, 6]});
举例
this.list = this.list.map((item, index) => {return {...item,direction: 'left',};});
5. some() 和 every()
some()
: 返回一个boolean,判断是否有元素是否符合函数条件。数组里面所有的元素只要有一个符合条件就返回true。
every()
:返回一个boolean,判断每个元素是否符合函数条件。数组里面所有的元素都符合条件才返回true。
every 和 some 都只是判断,不做处理,不生成新的数组。
// every 中每一个元素都要大于3 返回 true, 否则返回 falselet a = [1, 2, 3, 4, 5, 6];let b= a.every((num, index, a) => {return num > 3;})console.log(b) // false // some 中任意一个只要大于3 返回 true, 没有任何一个 返回 falselet c= a.some((num, index, a) => {return num > 3;})console.log(c) // true
使用技巧:
every和some都通过控制return的值来跳出循环。
具体做法是:
every方法返回值是布尔类型,最终返回值为true需要每一次回调函数返回值都为true,如果某一次回调函数返回值为false,则every方法结束对数组的遍历并返回false,所以在想要跳出循环时回调函数return false,因为every会对callback回调函数中的返回值做的判断处理类似于&&。
some方法返回值是布尔类型,最终返回值为true只需要任意一次回调函数返回值为true就会结束对数组的遍历,如果每一次回调函数返回值都为false,则some方法就会一直遍历下去并返回false,所以在想要跳出循环时回调函数return true,因为some会对callback回调函数中的返回值做的判断处理类似于||。
实际运用中,如果希望跳出循环时得到的判断值为true的话则用some,如果希望跳出循环时得到的判断值为false的话则用every。比如在判定用户是否勾选了不可操作的数据,或者是否勾选了一条可以操作的数据可以使用这两个方法遍历循环数组。
6. reduce(),reduceRight()
reduce()
方法和reduceRight()
方法依次处理数组的每个成员,最终累计为一个值。
reduce
是从左到右处理(从第一个成员到最后一个成员),reduceRight
则是从右到左(从最后一个成员到第一个成员),其他完全一样。
// 累加求和let result = [1, 2, 3, 4, 5].reduce((a, b) => {console.log(a, b);return a + b;})console.log(result);// 1 2// 3 3// 6 4// 10 5//最后结果:15
reduce方法和reduceRight方法的第一个参数是一个函数
。该函数接受以下四个参数。
累积变量(必须)sum,默认为数组的第一个成员当前变量(必须)current,默认为数组的第二个成员当前位置(可选)(从0开始)原数组(可选)
如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数
。
let result2 = [1, 2, 3, 4, 5].reduce(function (a, b) {return a + b;}, 10);console.log(result2); // 25
上面的第二个参数相当于设定了默认值
,处理空数组时尤其有用,可避免一些空指针异常。
由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。
function findLongest(entries) {return entries.reduce((longest, entry) => {return entry.length > longest.length ? entry : longest;}, '');}let result = findLongest(['aaa', 'bb', 'c']);console.log(result); // "aaa"
上面代码中,reduce
的参数函数会将字符长度较长的那个数组成员,作为累积值。这导致遍历所有成员之后,累积值就是字符长度最长的那个成员
7.资源分享
es6循环部分
js在线编辑器,js在线运行