push
作用:向数组"末尾"追加新的内容
参数:追加的内容(可以是一个,也可是多个)
返回值:新增后数组的长度
原有数组改变
JavaScript
ini
var arr = [
{ name: 'lee', age: 36 },
{ name: 'wang', age: 31 }
];
arr.push({ name: 'song', age: 30 });
console.log(arr);
pop
作用:删除数组最后一项
参数:无
返回:被删除的那一项内容
原有数组改变
JavaScript
ini
var arr = [
{ name: 'lee', age: 36 },
{ name: 'wang', age: 31 },
{ name: 'gao', age: 50 }
];
arr.pop();
console.log(arr);
shift
作用:删除数组中的第一项
参数:无
返回:被删除的那一项内容
原有数组改变
JavaScript
ini
var arr = [
{ name: 'lee', age: 36 },
{ name: 'wang', age: 31 },
{ name: 'gao', age: 50 }
];
arr.shift();
console.log(arr);
unshift
作用:向数组开始位置追加新内容
参数:要新增的内容
返回:新增后数组的长度
原有数组改变
JavaScript
ini
var arr = [
{ name: 'lee', age: 36 },
{ name: 'wang', age: 31 },
{ name: 'gao', age: 50 }
];
arr.unshift({ name: 'xu', age: 33 }, {});
console.log(arr);
【删除:ary.splice(n,m)】
从索引n(start)开始,删除m(deleteCount)个内容,把删除的部分以一个新数组返回,原有数组改变
JavaScript
ini
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var ns = arr.splice(2, 3);
console.log(arr, ns);
如果不指定m或者删除的个数大于长度,都是删除到数组的末尾
【新增:ary.splice(n,0,x,...)】
从索引n(start)开始删除零项(没删除),把X(items)或者更多需要插入的内容存放到数组中索引N的"前面"
JavaScript
ini
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
arr.splice(4, 0, 100, 200, { name: 'qian', age: 45 });
console.log(arr);
【修改:ary.splice(n,m,x,...)】
修改的原理就是把原有内容删除掉,然后用新的内容替换这部分信息即可
JavaScript
ini
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var re = arr.splice(2, 1, 100, 200, { name: 'qian', age: 45 });
console.log(arr, re);
JavaScript
scss
//=>删除最后一项
ary.pop();
ary.splice(ary.length - 1);
ary.length--
JavaScript
ini
//=>向数组末尾追加新内容
ary.push(100);
ary.splice(ary.length, 0, 100);
ary[ary.length] = 1;
不建议基于delete删除数组中的某一项,虽然内容没有了,但是数组的length长度没有改变。
slice
作用:在一个数组中,按照条件查找出其中的部分内容
参数:两个参数(n/m),从索引n开始,找到索引m处,但是不包含m
返回:以一个新数组存储查找的内容
原有数组不会变
JavaScript
ini
var arr = [12, 23, 34, 45, 56, 67, 78, 89, 90];
var newArr1 = arr.slice(2, 7);
var newArr2 = arr.slice(2);
JavaScript
ini
var newArr3 = arr.slice(0);
var newArr4 = arr.slice();
var newArr5 = arr.slice(-3, -1);
console.log(arr);
console.log(newArr1);
console.log(newArr2);
console.log(newArr3, newArr3 === arr);
console.log(newArr4, newArr4 === arr);
console.log(newArr5);
实现数组的克隆:克隆的一个新数组,和原有数组内容一样,但不是相同的堆内存空间,两个数组不相等、独立的。
concat
作用:实现多个数组(或者值)的拼接
参数:数组或者值
返回:拼接后的新数组
原有数组不变
JavaScript
ini
var ary1 = [12, 23];
var ary2 = [100, 200];
var ary3 = [1000, 2000];
var newArr = ary1.concat(ary2, '珠峰', ary2, ary3);
console.log(newArr);
toString
作用:把数组转换为字符串参数:无
返回:数组中的每一项用逗号分隔的字符串
原有数组不变
JavaScript
ini
var ary1 = [12, 23, { name: 'lee', age: 29 }];
var str = ary1.toString();
console.log(str);
join
作用:和toString类似,也是把数组转换为字符串,但是我们可以设置变为字符串后,每一项之间的连接符参数:指定的链接符
返回:字符串
原有数组不变
JavaScript
ini
var ary1 = [12, 23, 34, 45, { name: 'lee', age: 29 }];
var str1 = ary1.join(',');
var str2 = ary1.join('+');
console.log(str1);
console.log(str2);
var num = eval([1, 2, 3, 45, 6, 7].join('+'));
console.log(num);
reverse
作用:把数组倒过来排列
参数:无
返回:排列后的新数组
原有数组改变
JavaScript
ini
var ary = [12, 23, 34, 45, { name: 'lee', age: 29 }];
ary.reverse();
console.log(ary);
sort
作用:给数组排序
参数:无/函数
返回:排序后的新数组
原有数组改变
JavaScript
css
var ary = [1, 3, 8, 3, 5, 7, 34, 89, 21];
ary.sort(function(a, b) {
return a - b; //升序
// return b-a; //降序
})
console.log(ary);
indexOf / lastIndexOf
这两个方法不兼容IE低版本浏览器(IE6~8)
作用:检测当前值在数组中第一次或者最后一次出现位置的索引
参数:要检测的值
返回:索引
原有数组不变
基于indexOf检测,如果数组中有这一项,返回一个大于等于零的索引,如果没有,返回的索引值为-1
JavaScript
ini
var obj = { name: 'lee', age: 29 };
var ary = [1, 3, 8, 3, 5, 7, obj, 34, 89, 21];
if (ary.indexOf(89) > -1) {
//ary包含100这项
console.log(`包含89`);
}
if (ary.indexOf(obj)) {
console.log(`包含${obj}这项`);
}
every
every()方法,针对数组中的每一个元素进行比对,只要有一个元素比对结果为false则返回false,反之要所有的元素比对结果为true才为true.
JavaScript
ini
var a = [1, 2, 3, 4, 5, 6];
var b = a.every(function(x) {
return x < 8;
})
var c = a.every(function(x) {
return x < 6;
})
console.log(b, c);
some
some()方法,同样是针对数组中的每一个元素,但是这个方法是,只要有一个元素比对结果为true,返回结果就为true,反之要所有的元素比对结果为false才为false
JavaScript
ini
var a = [1, 2, 3, 4, 5, 6];
var b = a.some(function(x) {
return x > 10;
})
var c = a.some(function(x) {
return x < 5;
})
console.log(b, c);
filter
scss
filter()方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素; 不会改变原始数组
JavaScript
ini
let oldArr = [
{ name: 'tom', age: 13 },
{ name: 'tom2', ge: 14 },
{ name: 'tom3', age: 15 },
{ name: 'tom4', age: 16 },
];
let newArr = oldArr.filter((item, index, arr) => {
return item.age >= 15
});
console.log(oldArr);
console.log(newArr);
函数返回布尔值
find
find() 返回数组中第一个满足条件的数据
JavaScript
javascript
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum1 = num.find((item, index) => {
return item > 40;
})
console.log("newNum1 = " + newNum1); //50
findIndex
findIndex() 返回数组中第一个满足条件的索引(从0开始), 不满足返回-1
JavaScript
javascript
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum2 = num.findIndex((item, index) => {
return item > 40;
})
console.log("newNum2 = " + newNum2); //4
**
**
includes
includes() 判断数组宏是否包含某值,返回 true 或 false
语法:arr.includes(searchElement[, fromIndex])
JavaScript
ini
var num = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var newNum7 = num.includes(40);
var newNum8 = num.includes(40, 5); //从索引5的位置开始向后查找
console.log("newNum7 = " + newNum7); //true
console.log("newNum8 = " + newNum8); //false
JavaScript
less
const arr = ['es6', 'es7', 'es8', 'es9']
console.log(arr.includes('es7')) // true
console.log(arr.includes('es7', 2)) // false ->从数组的第二个下标开始查找
console.log(arr.includes('es8', -1)) // false ->从数组的倒数第一个下标开始往后查找
console.log(arr.includes('es8', -2)) // true ->从数组的倒数第二个下标开始往后查找
const _arr = ['es6', ['es7', 'es8'], 'es9']
console.log(_arr.includes(['es7', 'es8'])) // false
console.log(_arr.indexOf( ['es7', 'es8'])) // -1
//includes、indexOf 都只能查找基本数据类型,不能查找复合数据类型
const __arr= ['es6', ['es7', 'es8'], NaN, 'es9', 2]
console.log(__arr.includes(NaN)) // true
console.log(__arr.indexOf( NaN)) // -1
console.log(__arr.includes(2)) // true
console.log(__arr.includes('2')) // false
console.log(__arr.indexOf(2)) // 4
console.log(__arr.indexOf('2')) // -1
****
foreach / map
foreach 和 map 都是数组的迭代方法,对数组的每一项执行给定函数,不会改变原数组。两者的区别就在于 foreach 没有返回值,而 map 会返回每项执行完毕后数据组成的新数组。
所以在选择迭代方法时,如果不需要返回新数组,就选择 foreach , 如果需要得到的新数组,就选择 map 。
Foreach
语法: array.forEach(function(currentValue, index, arr), thisValue)
forEach()方法用于调用数组的每一个元素,并将元素传递给回调函数
JavaScript
javascript
let colors = ['red', 'blue', 'green'];
colors.forEach((item, $index, arr) => {
console.log(`${item} => ${$index} => ${arr}`);
})
forEach采用抛出一个异常来终止循环 **
**
JavaScript
javascript
const arr = [1, 2, 3, 4, 5];
try {
arr.forEach(item => {
if (item === 3) {
throw ('终止循环'); // 抛出一个异常
}
console.log('val=' + item); // 1,2
});
} catch (e) {
console.log('catch内容:' + e); // catch内容:终止循环
}
使用 return 方式(不能终止)
跳过值为3时,再继续循环
JavaScript
javascript
/* 1.使用 return */
arr.forEach(item => {
if (item === 3) {
return; // 跳过itme为3
}
console.log('val=' + item); // 1,2,4,5
});
使用 break 方式(报错)
报错 Uncaught SyntaxError: Illegal break statement
JavaScript
ini
/* 2.使用 break */
arr.forEach(item => {
if (item === 3) {
break; // 报错 Uncaught SyntaxError: Illegal break statement
}
console.log('val=' + item);
});
使用 continue 方式(报错)
报错 Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement
JavaScript
ini
/* 3.使用 continue */
arr.forEach(item => {
if (item === 3) {
continue; // 报错 Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement
}
console.log('val=' + item);
});
map
语法:array.map(function(currentValue,index,arr), thisValue)
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。
JavaScript
javascript
var arr = [
{ name: "zs", age: 12 },
{ name: "ls", age: 13 },
{ name: "ww", age: 16 },
{ name: "whh", age: 20 },
];
var item = arr.map((ele, index) => {
return {
name: ele.name + "__技术部员工",
age: ele.age + 10
}
})
console.log(item);
keys
keys() 方法用于从数组创建一个包含数组键的可迭代对象。
如果对象是数组返回 true,否则返回 false。
c
语法:array.keys()
JavaScript
ini
var arr = [
{ name: "zs", age: 12 },
{ name: "ls", age: 13 },
{ name: "ww", age: 16 },
{ name: "whh", age: 20 },
];
var iterator = arr.keys();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
reduce
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce() 可以作为一个高阶函数,用于函数的 compose。
注意: reduce() 对于空数组是不会执行回调函数的。
javascript
语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
arr 表示将要原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。
常用的参数只有两个:prev 和 cur。
数组求和、求乘积
JavaScript
javascript
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x, y) => x + y)
var mul = arr.reduce((x, y) => x * y)
console.log(sum); //求和,10
console.log(mul); //求乘积,24
JavaScript
javascript
//函数参数求和
function foo(x, y, z) {
let sum = 0;
// Array.prototype.forEach.call(arguments, function(item) {
// sum += item
// })
Array.from(arguments).forEach(item => {
sum += item
})
return sum
}
console.log(foo(1,2,3)) // 6
JavaScript
javascript
function foo(...args) {
console.log(args) // [ 1, 2, 3 ]
let sum = 0
args.forEach(item => {
sum += item
})
return sum
}
let sum = foo(1,2,3)
console.log(sum) // 6
**
**
**
**
计算数组中每个元素出现的次数
JavaScript
ini
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre, cur) => {
if (cur in pre) {
pre[cur]++
} else {
pre[cur] = 1
}
return pre
}, {})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
数组去重
JavaScript
javascript
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
if (!pre.includes(cur)) {
return pre.concat(cur)
} else {
return pre
}
}, [])
console.log(newArr); // [1, 2, 3, 4]
JavaScript
javascript
let arr = [1,2,3,4,8,2,4,5]
let s = Array.from(new Set(arr))
console.log(s)
JavaScript
javascript
let arr1 = [1,2,3,4]
let arr2 = [3,5,6,8,2]
let s = Array.from(new Set([...arr1, ...arr2]))
console.log(s) //[1, 2, 3, 4, 5, 6, 8]
JavaScript
ini
let arr1 = [1,2,3,4,'world']
let arr2 = [3,5,'hello',6,8,2]
let arrAll=[...new Set(arr1.concat(arr2))]
console.log(arrAll) //[1, 2, 3, 4, 'world', 5, 'hello', 6, 8]
对象里属性求和
JavaScript
ini
var result = [
{ subject: 'math', score: 10 },
{ subject: 'chinese', score: 20 },
{ subject: 'english', score: 30 }
];
var sum = result.reduce(function(prev, cur) {
return cur.score + prev;
}, 0);
console.log(sum) //60
****js数组对象,按数组元素相同属性值分组
JavaScript
ini
const arr = [
{ id: 1, type: 'A', name: 'John' },
{ id: 2, type: 'B', name: 'Mike' },
{ id: 3, type: 'A', name: 'Sam' },
{ id: 4, type: 'C', name: 'David' },
{ id: 5, type: 'B', name: 'Adam' },
{ id: 6, type: 'A', name: 'Tom' },
];
const grouped = arr.reduce((acc, cur) => {
const key = cur.type;
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(cur);
return acc;
}, {});
console.log(grouped);
输出:
JavaScript
bash
{
A: [
{ id: 1, type: 'A', name: 'John' },
{ id: 3, type: 'A', name: 'Sam' },
{ id: 6, type: 'A', name: 'Tom' }
],
B: [
{ id: 2, type: 'B', name: 'Mike' },
{ id: 5, type: 'B', name: 'Adam' }
],
C: [
{ id: 4, type: 'C', name: 'David' }
]
}
这里使用 reduce() 方法,初始值为一个空对象 {}
,然后对于每个元素进行处理,将其归为对应类型的数组中,最终得到一个以类型为键,以对应类型的元素数组为值的对象。
【Array.isArray()、Array.from()】
**Array.from()方法
**
Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组。
那么什么是类数组对象呢?所谓类数组对象,最基本的要求就是具有length属性的对象。
Array.from有三个参数,Array.from(arrayLike[, mapFn[, thisArg]]),
arrayLike: 想要转换成数组的伪数组对象或可迭代对象;
mapFn: 如果指定了该参数,新数组中的每个元素会执行该回调函数;
thisArg: 可选参数,执行回调函数 mapFn 时 this 对象。该方法的返回值是一个新的数组实例(真正的数组)。
将类数组对象转换为真正数组:
JavaScript
bash
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
那么,如果将上面代码中length属性去掉呢?实践证明,答案会是一个长度为0的空数组。
这里将代码再改一下,就是具有length属性,但是对象的属性名不再是数字类型的,而是其他字符串型的,代码如下:
JavaScript
javascript
let arrayLike = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane','john','Mary'],
length: 4
}
let arr = Array.from(arrayLike)
console.log(arr) // [ undefined, undefined, undefined, undefined ]
会发现结果是长度为4,元素均为undefined的数组
由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组。
2、该类数组对象的属性名必须为数值型或字符串型的数字
ps: 该类数组对象的属性名可以加引号,也可以不加引号
将Set结构的数据转换为真正的数组:
JavaScript
csharp
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set)) // [ 12, 45, 97, 9797, 564, 134, 45642 ]
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下
JavaScript
javascript
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) // [ 13, 46, 98, 9798, 565, 135, 45643 ]
将字符串转换为数组:
JavaScript
python
let str = 'hello world!';
console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
Array.from参数是一个真正的数组:
JavaScript
javascript
console.log(Array.from([12,45,47,56,213,4654,154]))
像这种情况,Array.from会返回一个一模一样的新数组
在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。
JavaScript
matlab
function doSomething (){
return [...arguments]
}
doSomething('a','b','c'); // ["a","b","c"]
只要是部署了iterator接口的数据结构,Array.from都能将其转为数组:
在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。
在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。
只要是部署了iterator接口的数据结构,Array.from都能将其转为数组:
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,处理后的值放入返回的数组。
JavaScript
javascript
Array.from([1, 2, 3], (x) => x * x)// [1, 4, 9]
// 等同于
Array.from([1,2,3].map(x => x * x))
如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this。
Array.from()可以将各种值转为真正的数组,并且还提供map功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。
JavaScript
css
Array.from({ length: 2 }, () => 'jack')// ['jack', 'jack']
Array.isArray() 判断是不是数组
JavaScript
javascript
// 下面的函数调用都返回 true
console.log(Array.isArray([]));
console.log(Array.isArray([1]));
console.log(Array.isArray(new Array()));
// 下面的函数调用都返回 false
console.log(Array.isArray());
console.log(Array.isArray({}));
console.log(Array.isArray(null));
console.log(Array.isArray(undefined));
console.log(Array.isArray(17));
console.log(Array.isArray('Array'));
console.log(Array.isArray(true));
console.log(Array.isArray(false));
JavaScript
javascript
var lis = document.querySelector('li');
console.log(Array.isArray(lis)); //false
var lis2 = Array.from(lis);
console.log(Array.isArray(lis2)); //true
【Array.of()】将一系列值转换成数组
当调用 new Array( )构造器时,根据传入参数的类型与数量的不同,实际上会导致一些不同的结果, 例如:
JavaScript
ini
let items = new Array(2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // undefined
console.log(items[1]) ;
JavaScript
javascript
let items = new Array(1, 2) ;
console.log(items.length) ; // 2
console.log(items[0]) ; // 1
console.log(items[1]) ; // 2
当使用单个数值参数来调用 Array 构造器时,数组的长度属性会被设置为该参数。 如果使用多个参数(无论是否为数值类型)来调用,这些参数也会成为目标数组的项。数组的这种行为既混乱又有风险,因为有时可能不会留意所传参数的类型。
ES6 引入了Array.of( )方法来解决这个问题。该方法的作用非常类似Array构造器,但在使用单个数值参数的时候并不会导致特殊结果。Array.of( )方法总会创建一个包含所有传入参数的数组,而不管参数的数量与类型:
JavaScript
ini
let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]); // 1
console.log(items[1]); // 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]); // 2
Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载,而且他们的行为非常统一。
JavaScript
ini
const arr = Array.of(1);
console.log(arr); //[1]
copyWithin()
copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。
返回修改后的数组(即直接修改原数组),不会改变数组的长度
Bash
sql
array.copyWithin(target, start, end)
target为必需,复制到指定位置目标索引,可以为负值,为负值后,索引为length+target
start 可选,元素复制的起始位置,省略,默认为0。可以为负值,为负值后,索引为length+start
end 可选,元素复制的结束位置(不包含),默认为数组的length,可以为负值,为负值后,索引为length+end
若start的值大于end,则直接返回原数组,不进行任何处理
JavaScript
css
var arr = ["apple","banana","cover","double"]
arr.copyWithin(1,2,3)
console.log(arr)
// Array [ "apple", "cover", "cover", "double" ]
start和end是先进行比较大小,然后在进行负值处理,
JavaScript
css
var arr = [ "apple", "banana", "cover", "double" ]
arr.copyWithin(0,-3,-1)
console.log(arr)
// Array [ "banana", "cover", "cover", "double" ]
flat()
数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组"拉平",变成一维数组。该方法返回一个新数组,对原数据没有影响。
JavaScript
ini
let arr = [1, 2, [3, 4]]
let newArr = arr.flat()
console.log(newArr) //[1, 2, 3, 4]
上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。
flat()默认只会"拉平"一层,如果想要"拉平"多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
JavaScript
ini
let arr = [1, 2, [3, 4]]
let newArr = arr.flat()
console.log(newArr) // [1, 2, 3, 4]
arr = [1, 2, [3, [4, 5]]]
newArr = arr.flat(2)
console.log(newArr) // [1, 2, 3, 4, 5]
上面代码中,flat()的参数为2,表示要拉平两层的嵌套数组。
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
JavaScript
ini
let arr = [1, 2, [3, [4, 5]]]
let newArr = arr.flat(Infinity)
console.log(newArr) // [1, 2, 3, 4, 5]
如果原数组有空位,flat()方法会跳过空位。
JavaScript
ini
arr = [1, 2, , 4, 5]
newArr = arr.flat(Infinity)
console.log(newArr) // [1, 2, 4, 5]
flatMap()方法对原数组的每个成员执行一个函数,相当于执行Array.prototype.map(),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
JavaScript
ini
let arr = [1, 2, 3, 4, 5]
let newArr=arr.flatMap(x => {
return [x, x*2]
})
console.log(newArr) // [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
entries()
entries()
方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
语法
scss
arr.entries()
返回值
一个新的 Array
迭代器对象。Array Iterator是对象,它的原型(proto :Array Iterator)上有一个next方法,可用用于遍历迭代器取得原数组的 [key,value]。
1、 Array Iterator
JavaScript
ini
var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator);
2、iterator.next()
JavaScript
ini
var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator.next());
Bash
vbnet
// iterator.next() 返回一个对象,对于有元素的数组,
// 是 next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是 false,
// 直到迭代器结束 done 才是 true。
// next.value 是一个 ["key","value"] 的数组,是返回的迭代器中的元素值。
3、iterator.next 方法运行
JavaScript
ini
var arr = ["a", "b", "c"];
var iter = arr.entries();
var a = [];
// for(var i=0; i< arr.length; i++){ // 实际使用的是这个
for(var i=0; i< arr.length+1; i++){ // 注意,是 length+1,比数组的长度大
var tem = iter.next(); // 每次迭代时更新 next
console.log(tem.done); // 这里可以看到更新后的 done 都是 false
if(tem.done !== true){ // 遍历迭代器结束 done 才是 true
console.log(tem.value);
a[i]=tem.value;
}
}
console.log(a); // 遍历完毕,输出 next.value 的数组
4、二维数组按行排序
JavaScript
ini
function sortArr(arr) {
debugger
var goNext = true;
var entries = arr.entries();
while (goNext) {
var result = entries.next();
if (result.done !== true) {
result.value[1].sort((a, b) => a - b);
goNext = true;
} else {
goNext = false;
}
}
return arr;
}
var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]];
sortArr(arr);
console.log(arr)
5、使用for...of 循环 -for-of / for-in
无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。
for...of
语句遍历可迭代对象定义要迭代的数据。
javascript
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
let iterable = [3, 5, 7];
iterable.foo = 'hello';
for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i in iterable) {
if (iterable.hasOwnProperty(i)) {
console.log(i); // logs 0, 1, 2, "foo"
}
}
for (let i of iterable) {
console.log(i); // logs 3, 5, 7
}
for...in 会迭代原型链上的所有可枚举属性,如需迭代当前对象的可枚举属性,可以使用 obj.hasOwnProperty(key)进行拦截,并且它不记录值,只记录键。
1 遍历数组通常用for循环
ES5的话也可以使用forEach,ES5具有遍历数组功能的还有map、filter、some、every、reduce、reduceRight等,只不过他们的返回结果不一样。但是使用foreach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数。
JavaScript
ini
Array.prototype.method=function(){
console.log(this.length);
}
var myArray=[1,2,4,5,6,7]
myArray.name="数组"
for (var index in myArray) {
console.log(myArray[index]);
}
2 for in遍历数组的毛病
1.index索引为字符串型数字,不能直接进行几何运算
2.遍历顺序有可能不是按照实际数组的内部顺序
3.使用for in会遍历数组所有的可枚举属性,包括原型。例如上栗的原型方法method和name属性
所以for in更适合遍历对象,不要使用for in遍历数组。
那么除了使用for循环,如何更简单的正确的遍历数组达到我们的期望呢(即不遍历method和name),ES6中的for of更胜一筹.
JavaScript
ini
Array.prototype.method=function(){
console.log(this.length);
}
var myArray=[1,2,4,5,6,7]
myArray.name="数组";
for (var value of myArray) {
console.log(value);
}
记住,for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。
for of遍历的只是数组内的元素,而不包括数组的原型属性method和索引name
3 遍历对象
遍历对象 通常用for in来遍历对象的键名
JavaScript
javascript
Object.prototype.method=function(){
console.log(this);
}
var myObject={
a:1,
b:2,
c:3
}
for (var key in myObject) {
console.log(key);
}
for in 可以遍历到myObject的原型方法method,如果不想遍历原型方法和属性的话,可以在循环内部判断一下,hasOwnPropery方法可以判断某属性是否是该对象的实例属性
JavaScript
scss
for (var key in myObject) {
if(myObject.hasOwnProperty(key)){
console.log(key);
}
}
同样可以通过ES5的Object.keys(myObject)获取对象的实例属性组成的数组,不包括原型方法和属性
JavaScript
javascript
Object.prototype.method=function(){
console.log(this);
}
var myObject={
a:1,
b:2,
c:3
}
总结
-
for..of适用遍历数/数组对象/字符串/map/set等拥有迭代器对象的集合.但是不能遍历对象,因为没有迭代器对象.与forEach()不同的是,它可以正确响应break、continue和return语句
-
for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用for-in循环(这也是它的本职工作)或内建的Object.keys()方法:
JavaScript
vbnet
for (var key of Object.keys(someObject)) {
console.log(key + ": " + someObject[key]);
}
- 遍历map对象时适合用解构,例如;
JavaScript
javascript
for (var [key, value] of phoneBookMap) {
console.log(key + "'s phone number is: " + value);
}
- 当你为对象添加myObject.toString()方法后,就可以将对象转化为字符串,同样地,当你向任意对象添加myObjectSymbol.iterator方法,就可以遍历这个对象了。
举个例子,假设你正在使用jQuery,尽管你非常钟情于里面的.each()方法,但你还是想让jQuery对象也支持for-of循环,你可以这样做:
JavaScript
javascript
jQuery.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
所有拥有Symbol.iterator的对象被称为可迭代的。在接下来的文章中你会发现,可迭代对象的概念几乎贯穿于整门语言之中,不仅是for-of循环,还有Map和Set构造函数、解构赋值,以及新的展开操作符。
- for...of的步骤
for-of循环首先调用集合的Symbol.iterator方法,紧接着返回一个新的迭代器对象。迭代器对象可以是任意具有.next()方法的对象;for-of循环将重复调用这个方法,每次循环调用一次。举个例子,这段代码是我能想出来的最简单的迭代器:
JavaScript
javascript
var zeroesForeverIterator = {
[Symbol.iterator]: function () {
return this;
},
next: function () {
return {done: false, value: 0};
}
};
JS数组遍历:
1.普通for循环
JavaScript
ini
var arr = [1,2,0,3,9];
for ( var i = 0; i <arr.length; i++){
console.log(arr[i]);
}
2.优化版for循环
使用变量,将长度缓存起来,避免重复获取长度,数组很大时优化效果明显
JavaScript
ini
for(var j = 0,len = arr.length; j < len; j++){
console.log(arr[j]);
}
3.forEach
ES5推出的,数组自带的循环,主要功能是遍历数组,实际性能比for还弱
JavaScript
javascript
arr.forEach(function(value,i){
console.log('forEach遍历:'+i+'--'+value);
})
forEach这种方法也有一个小缺陷:你不能使用break语句中断循环,也不能使用return语句返回到外层函数。
4.map遍历
map即是 "映射"的意思 用法与 forEach 相似,同样不能使用break语句中断循环,也不能使用return语句返回到外层函数。
JavaScript
javascript
arr.map(function(value,index){
console.log('map遍历:'+index+'--'+value);
});
map遍历支持使用return语句,支持return返回值
JavaScript
kotlin
var temp=arr.map(function(val,index){
console.log(val);
return val*val
})
console.log(temp);
forEach、map都是ECMA5新增数组的方法,所以ie9以下的浏览器还不支持
5.for-of遍历
ES6新增功能
JavaScript
scss
for( let i of arr){
console.log(i);
}
5.1 for-of这个方法避开了for-in循环的所有缺陷
5.2与forEach()不同的是,它可以正确响应break、continue和return语句
for-of循环不仅支持数组,还支持大多数类数组对象,例如DOM NodeList对象。for-of循环也支持字符串遍历
JS对象遍历:
1.for-in遍历
for-in是为遍历对象而设计的,不适用于遍历数组。(遍历数组的缺点:数组的下标index值是数字,for-in遍历的index值"0","1","2"等是字符串)
for-in循环存在缺陷:循环会遍历对象自身的和继承的可枚举属性(不含Symbol属性)
JavaScript
ini
for (var index in arr){
console.log(arr[index]);
console.log(index);
}
2.使用Object.keys()遍历
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性).
JavaScript
ini
var obj = {'0':'a','1':'b','2':'c'};
Object.keys(obj).forEach(function(key){
console.log(key,obj[key]);
});
3.使用Object.getOwnPropertyNames(obj)遍历
返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性).
JavaScript
ini
var obj = {'0':'a','1':'b','2':'c'};
Object.getOwnPropertyNames(obj).forEach(function(key){
console.log(key,obj[key]);
});
4.使用Reflect.ownKeys(obj)遍历
返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举.
JavaScript
ini
var obj = {'0':'a','1':'b','2':'c'};
Reflect.ownKeys(obj).forEach(function(key){
console.log(key,obj[key]);