基础系列文章:
JavaScript 基础(一):null 和 undefined
最近一直没有更新了。
原因无非就是工作忙了一点。还有就是对于这个 Array 要写的东西确实比较多。
本篇文章会分多次更新。(更新完成)
在文章中,如果是 ES6 新增的方法,会标红作为提示。
一、Array 构造器
构造器:用于创建一个新的数组。
通常有两种方式:对象字面量、构造器方式。
下面是代码:
// 对象字面量方式 let arr = [1, 2] // 构造器方式 let arr1 = Array(1, 2) console.log(arr === arr1) console.log('arr:', arr, 'arr1:', arr1)
对于构造器方式,有两点要说明:
1、是使用 new 还是使用函数调用方式,ECMA 给的解释是都一样;一般来说直接函数调用简便。
2、参数,当只有一个参数时,表示创建数组的长度;0 或 2个以上参数,作为数组元素。
var arr1 = Array(4) console.log('array 1 参数:', arr1) // array 1 参数: [ <4 empty items> ] arr1 = Array() console.log('array 0 参数:', arr1) // array 0 参数: [] arr1 = Array(1,2,3,4) console.log('array 2 参数以上:', arr1) // array 2 参数以上: [ 1, 2, 3, 4 ]
二、ES6 新增的一些构造数组方法
1、Array.of(ES6)
用于将参数依次转化为数组的项。即使只有一个参数也作为数组的项
// 和 Array 区别(一个参数) let arr2 = Array.of(2) console.log('arr2 by Array.of:', arr2) // arr2 by Array.of: [ 2 ] arr2 = Array.of(4, 5, 6) console.log('arr2 by Array.of:', arr2) // arr2 by Array.of: [ 4, 5, 6 ]
2、Array.from(ES6)
用于从一个可迭代对象创建数组。设计初衷是为了快速创建数组。
下面展示用法:
// 当使用 function 和箭头函数时,中间打印结果会不一样 let obj = { 0: 'a', 1: 'b', 2: 'c', length: 3 } let arr3 = Array.from( obj, function(value, index){ console.log(value, index, this, arguments.length) return value.repeat(3) // 必须指定返回,否则返回的是 undefined }, obj ) // 打印结果 // a 0 { '0': 'a', '1': 'b', '2': 'c', length: 3 } 2 // b 1 { '0': 'a', '1': 'b', '2': 'c', length: 3 } 2 // c 2 { '0': 'a', '1': 'b', '2': 'c', length: 3 } 2 let obj = { 0: 'a', 1: 'b', 2: 'c', length: 3 } let arr3 = Array.from( obj, (value, index) =>{ console.log(value, index, this, arguments.length) return value.repeat(3) // 必须指定返回,否则返回的是 undefined }, obj ) // 打印结果 // a 0 {} 5 // b 1 {} 5 // c 2 {} 5
对于第一个参数:可迭代对象可以是 string、set、map、arguments
// 可以作为参数的可迭代对象有:string、set、map、arguments console.log('array from String', Array.from('abc')) // array from String [ 'a', 'b', 'c' ] console.log('array from Set', Array.from(new Set(['abc', 'def']))) // array from Set [ 'abc', 'def' ] console.log( 'array from Map', Array.from( new Map([ [1, 'abc'], [2, 'def'], ]) ) ) // array from Map [ [ 1, 'abc' ], [ 2, 'def' ] ] function fn() { return Array.from(arguments) } console.log('array from arguments:', fn(1, 2, 3)) // array from arguments: [ 1, 2, 3 ]
一个重要使用场景:生成一个从0到n 的数组
// length 就是要生成的数组个数 console.log( '0-n array:', Array.from({ length: 10 }, (v, i) => i) ) // 0-n array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
三、类型检测和原型
1、类型检测
现在检测数组都是用 Array.isArray(ES5 新增),对于以前的检测方法也要了解。
在 ES5 以前,Array 的检测并没有一个统一的标准,一般使用的方法有:
let arr5 = [] // instanceof console.log('instanceof', arr5 instanceof Array) // constructor console.log('constructor:', arr5.constructor === Array) // Array.prototype.isPrototypeOf console.log('isPrototypeOf:', Array.prototype.isPrototypeOf(arr5)) // Object.getPrototypeOf console.log('getPrototypeOf', Object.getPrototypeOf(arr5) === Array.prototype) // Object.prototype.toString console.log('prototype.tostring',Object.prototype.toString.apply(arr5) === '[object Array]')
上面的检测一般情况返回都是 true。
针对这些检测方法存在一些问题:
a、如 let arr6 = {__proto__: Array.prototype},对 arr6 使用上面的类型检测返回的都是 true,但 arr6 并不是 Array(可以称为伪造)
b、在多页面系统中,由于每个页面的 Array 引用地址都不一样,在一个页面检测另一个页面的 Array 就会不准确,可以直接在不同页面
if (!Array.isArray) { Array.isArray = function (arg) { return Object.prototype.toString.call(arg) === '[object Array]' } }
看浏览器是否支持 isArray,不支持使用 Object.prototype.toString 实现 isArray 函数。
console.log('Array.prototype is Array:', Array.isArray(Array.prototype)) // true console.log( 'Array.prototype is Array:', Object.prototype.toString.call(Array.prototype) === '[object Array]' ) // true console.log('Array property:', Object.getOwnPropertyNames(Array.prototype)) // 返回当前 Array 的方法
四、填鸭辩型
在开始展示 Array 的方法前,先来说一个词:填鸭辩型。
填鸭辩型,在这里的意思是:Array 的方法,由于设计上的巧妙可以用于类数组对象。
下面就用 Array.push 来演示下:(使用填鸭辩型特别注意类数组对象的 length 属性)
/** * length 正确匹配属性个数,直接添加并 length+1 * 1、当不存在 length 或者不能转为数值的时候,会替换第一个;length 不存在时会创建;length 为0 同; * 2、length 的值小于对象中属性个数;相当于在 length 处插入; * 3、length 的值大于等于对象中属性数,在最后添加,索引会跳跃;length 也会增加; */ // 当 length 正确匹配属性个数 let obj = { 0: 'football', 1: 'basketball',length :2 } let objPushInt = Array.prototype.push.call(obj, 'golfball') console.log('obj pushed:', obj) // obj pushed: { '0': 'football', '1': 'basketball', '2': 'golfball', length: 3 } console.log('objPushInt:', objPushInt) // objPushInt: 3 // 情形-1:length 不存在 let obj2 = { 0: 'football', 1: 'basketball' } objPushInt = Array.prototype.push.call(obj2, 'golfball') console.log('obj2 pushed:', obj2) // obj2 pushed: { '0': 'golfball', '1': 'basketball', length: 1 } console.log('objPushInt:', objPushInt) // objPushInt: 1 // 情形-2:length 小于属性个数 objPushInt = Array.prototype.push.call(obj2, 'volleyball') console.log('obj2 pushed(lenght):', obj2) // obj2 pushed(lenght): { '0': 'golfball', '1': 'volleyball', length: 2 } console.log('objPushInt:', objPushInt) // objPushInt: 2 // 情形-3:length 大于属性个数 obj2.length = 100 objPushInt = Array.prototype.push.call(obj2, 'football') console.log('obj2 pushed(lenght==):', obj2) // obj2 pushed(lenght==): { '0': 'golfball', '1': 'volleyball', '100': 'football', length: 101 } console.log('objPushInt:', objPushInt) // objPushInt: 101
五、改变数组的9个方法
在 MDN 上面的说法是:修改器方法,就是可以使原数组改变的方法。
1、push
push 向数组尾部添加一个或多个元素,并返回新数组长度;该方法可以模拟栈的入栈操作(配合 pop 实现);可以模拟出入队列(配合 shift 实现);
可以使用“填鸭辩型”
/** * 语法:array.push(element1,...,elementN) */ let arr8 = ['football', 'basketball', 'volleyball'] let pushInt = arr8.push('golfball') console.log('arr8 pushed:', arr8) console.log('pushInt:', pushInt) // 利用 push 根据 length 插入元素,可以实现数组合并(这里使用 apply 和call 的结果不一样) let arr8_1 = ['red', 'blue'] pushInt = Array.prototype.push.apply(arr8, arr8_1) console.log('合并后数组:', arr8) console.log('合并后长度:', pushInt)
2、pop
pop 用于删除数组的最后一个元素,并返回这个元素;该方法可以模拟栈的出栈(配合 push 实现);也可以模拟队列的出队列(配合 unshift 实现);
pop 和 push 配合使用就可以实现栈数据结构(JS 中没有栈,可以自行实现)
可以使用“填鸭辩型”
/** * 语法:array.pop() */ let arr7 = ['cat', 'dog', 'cow', 'chicken', 'mouse'] let popItem = arr7.pop() console.log('arr7 poped:', arr7) console.log('popItem:', popItem)
3、shift
shift 删除数组的第一个元素,并返回这个元素;可以模拟栈的出栈(配合 unshift 实现);也可以模拟队列的出队列(配合 push 实现);
可以使用“填鸭辩型”
/** * array.shift() */ let arr10 = [1, 2, 3, 4, 5] let shiftItem = arr10.shift() console.log('arr10 shift:', arr10) // arr10 shift: [ 2, 3, 4, 5 ] console.log('shiftItme:', shiftItem) // shiftItme: 1
4、unshift
unshift 向数组头部添加元素,可添加多个,返回新数组长度;可模拟栈的入栈(配合 shift 实现);也可以模拟队列的入队列(配合 pop 实现);
可以使用“填鸭辩型”
/** * array.unshift(element1,....,elementN) */ let arr11 = [1, 2, 3, 4, 5] let unshiftInt = arr11.unshift(10, 12) console.log('arr11 unshift:', arr11, ',unshiftInt:', unshiftInt)
5、fill(ES6)
fill 用一个固定值替换数组中从起始索引到结束索引(不包括结束索引),返回改变后数组引用(即原数组引用),原数组长度不变;
可以使用“填鸭辩型”
/** * 语法:array.fill(value[,start[,end=this.length]]) */ /** * 参数: * 1、value:要替换为的值; * 2、start:可选,起始位置;没有传入,全部替换; * 3、end:可选,结束索引,默认到最后;小于 start 不替换; */ let arr16 = [1, 2, 3, 4, 5, 6, 7, 8, 9] let arrFill = arr16.fill(100, 2, 5) // 一般示例 let arrFill = arr16.fill(100) // 没有起始位置,全部替换 let arrFill = arr16.fill(100, 4) // 有起始位置,从起始位置到最后 let arrFill = arr16.fill(100, -20, -15) // 不在范围内,不替换 let arrFill = arr16.fill(100, 4, 2) // end 小于 start,不替换
6、sort
用于对数组排序,返回排序后的数组;
可以使用“填鸭辩型”
/** * 语法:array.sort([comparefn]) * 可选参数:comparefn * 省略时:数组元素将按照各自转换为字符的 Unicode 位点进行排序(如:Boy 排在 apple 前,数字 25 排在 8 前) */ let arr12 = ['apple', 'Boy', 'cat', 'dog'] console.log('arr12 sorted:', arr12.sort()) arr12 = [4, 10, 20, 15] console.log('arr12 number sorted:', arr12.sort()) /** * comparefn 有值: * 1、若 comparefn(a,b)<0,a 将排在 b 前面 * 2、若 comparefn(a,b)=0,a 和 b 的相对位置不变 * 3、若 comparefn(a,b)<0,a 和 b 的位置对调 */ // 数字的comparefn 可以这么写 function compareNum(a, b) { return a - b } // 对于字符的,需要使用 localeCompare,排到正确顺序(本地 node 无效,浏览器下可以) let arr13 = ['互', '联', '网', '改', '变', '世', '界'] let arr13_1 = arr13.sort() let arr13_2 = ['互', '联', '网', '改', '变', '世', '界'] let arr13_3 = arr13_2.sort(function (a, b) { return a.localeCompare(b) }) console.log('arr13 sort:', arr13_1, ' by localeCompare sort:', arr13_3)
7、reverse
reverse 使数组倒置,返回引用;可以使用“填鸭辩型”
let arr9 = [1, 2, 3, 4, 5] console.log('arr9:', arr9) let arr9_1 = arr9.reverse() console.log('reverse arr9:', arr9_1)
8、splice
splice 改变数组,维持原数组引用,就地删除或者新增;
可以使用“填鸭辩型”
/**; * 语法:array.splice(start,deleteCount,[item1[,item2]....]) */ /** * 参数说明: * 1、start:开始删除的索引;start 大于 length,则不删除;负值,是从 length+start 位置处删除,相加后还为负值,从0处开始删除; * 2、deleteCount:删除的个数;0 不删除,但应该至少添加一个元素;大于 start 后面的元素个数,后面全部删除; * 3、itemN:要添加的项; * 4、返回值:删除的数组,没有删除,返回空数组; */ let arr14 = [1, 2, 3, 4, 5, 6, 7, 8, 9] let spliceArr = arr14.splice(4, 3, 10, 11, 12, 15) console.log('arr14 spliced:', arr14, ' spliceArr:', spliceArr) spliceArr = arr14.splice(-8, 1) console.log('arr14 spliced start=-8:', arr14, ' spliceArr:', spliceArr) spliceArr = arr14.splice(-15, 1) console.log('arr14 spliced start=-15:', arr14, ' spliceArr:', spliceArr) // 删除数组中的某个元素(当不存在时,把最后一个删除了,所以要判断) arr14.splice(arr14.indexOf(3), 1) console.log('arr14 delete 3:', arr14)
9、copyWithin(ES6)
copyWithin 用于数组内元素的替换,替换元素和被替换元素都是数组内的;原数组长度不变;
可以使用“填鸭辩型”
/** * 语法:copyWithin(target,start,[end=this.length]) */ /** * 参数说明: * 1、target:目标元素,将被替换掉元素的索引; * 2、start:替换元素在数组中的起始索引; * 3、end:可选,默认为数组长度;end 小于 start时,不会替换;start 和 end 决定了替换和被替换的长度; * 4、返回:返回改变后数组的引用; */ let arr15 = [1, 2, 3, 4, 5, 6, 7, 8, 9] // let copyWithinArr = arr15.copyWithin(6, 3) // let copyWithinArr = arr15.copyWithin(6, 3, 1) let copyWithinArr = arr15.copyWithin(6, 3, 4) console.log('arr15 copyWinthin:', arr15, ' copyWithinArr:', copyWithinArr)
六、不改变数组的9个方法
这些方法在 MDN 上面是:访问方法。不会改变自身,会返回一个新的数值或一个期望值。
1、join
join 用于使用给定的字符串连接数组的各个项。
可以使用“填鸭辩型”
/** * join 用指定的字符连接数组中的所有项,并返回连接后的字符串; * 默认不传值,是用【,】连接 */ let arr18 = ['my', 'name', 'is', 'ZHT'] let arrJoin = arr18.join() arrJoin = arr18.join(' ') arrJoin = arr18.join('-')
2、toString
toString 用于连接数组的各个项,并返回这个字符串;
/** * 内在操作是:每个项目 toString,后使用 join 连接各个项;所以不能使用“填鸭辩型”,Object 中没有 join(虽然 Array.join 可以使用在 Object 上面,但是 Object 本身没有) * 所以是用【,】连接的各个项
*/ let arr20 = [1, 2, 3, 4, 5, 6] let arrToString = arr20.toString() console.log('arr20:', arr20, ' arrToString:', arrToString)
3、toLocaleString
toLocaleString 和上面的 toString 一样,只是在转换的时候本地化
4、toSource
toSource 返回当前数组字面量的字符串。这个一般没有被实现。
5、indexOf
indexOf 用于从数组中查找第一个和给定值相等的索引,不存在返回 -1
/** * 使用的是严格相等 * 语法:array.indexOf(element[,start]) * start 是开始查找位置,默认 0; */ let arr21 = [1, 2, 3, 4, 5, 6, 7, 8] let arrIndexInt = arr21.indexOf(5) console.log('arr21:', arr21, ' arrIndexInt:', arrIndexInt) // 找出数组中某一个值的所有出现位置 function GetArrayAllIndex(arr, value) { let indices = [] let idx = arr.indexOf(value) while (idx !== -1) { indices.push(idx) idx = arr.indexOf(value, idx + 1) } return indices } let allIndex = GetArrayAllIndex( ['a', 'b', 'c', 'd', 'e', 'a', 'g', 'a', 'a'], 'a' ) console.log('allIndex:', allIndex) // allIndex: [ 0, 5, 7, 8 ]
6、lastIndexOf
lastIndexOf 从数组中查找给定值的索引,是从数组尾部向前查找。
start 为负值时,从(start + length) 处开始查找
7、includes(ES6)
includes 验证数组中是否包含给定值。
/** * includes 用于判断数组中是否存在要查找的值;有 true ,没有 false; * 语法:array.includes(value[,start]) */ let arr22 = [1, 2, 3, 4, 5, 6, 7] console.log('arr includes 5:', arr22.includes(5)) /** * 和 indexOf 有一点区别: * includes 可以判断 NaN ,indexOf 不可用 */ let arr22_1 = [1, 2, 3, 4, 5, NaN, 7] console.log('arr includes NaN:', arr22_1.includes(NaN)) // true console.log('arr indexOf NaN:', arr22_1.indexOf(NaN)) // -1
8、concat
concat 用于连接数组、多个数组、数组项等,并返回新的数组;
可以使用“填鸭辩型”
/** * concat 用于连接数组、多个数组、值到当前数组尾部,并返回新的数组;原数组不变;会对传入的值扁平化处理(只能处理一级,对于嵌套的不行)。 * 返回的数组中原数组中的项是--浅复制--过去的; */ let arr17 = [{ a: 1 }, 2, 3, 4] let arrConcat = arr17.concat(5, [6, 7, [8,9]]) console.log('arrConcat:', arrConcat) // [ { a: 1 }, 2, 3, 4, 5, 6, 7, [ 8, 9 ] ] console.log('arr17[0] === arrConcat[0]:', arr17[0] === arrConcat[0]) // true
9、slice
slice 用于从原数组浅复制一部分项到新数组;
可以使用“填鸭辩型”
/** * slice 用于从原数组【浅复制】一部分项到新数组;返回这个新数组,原数组不变 */ /** * 语法:array.slice([start[,end]]) * 参数: * 1、start:可选,开始索引;负值,表示倒数第几个开始,默认 0; * 2、end:可选,结束索引;不包括该项;默认 length; */ let arr19 = [0, 1, 2, 3, 4, 5, 6, 7] let arrSlice = arr19.slice(1, 5) console.log('arr19:', arr19, ' arrSlice:', arrSlice) // 当数组中有引用类型存在时,slice 生成的新数组是浅复制的 // 当新数组中的值改变时,原数组也会改变 let arr19_1 = [{ a: 100 }, 101, 102, 103] let arrSlice_1 = arr19_1.slice(0, 3) console.log('arr19_1:', arr19_1, ' arrSlice_1:', arrSlice_1) arrSlice_1[0].a = 200 console.log('arr19_1:', arr19_1, ' arrSlice_1:', arrSlice_1)
七、数组的12个遍历方法
1、forEach
forEach 对数组的每一项执行传入的函数,如果函数操作了项,原数组改变;返回 undefined
/** * forEach 对数组中的每个项都执行一次传入的函数;如果函数操作了项,原数组改变;返回值 undefined; * 对于删除的、新增的、未初始化的会跳过,不执行; * 语法:array.forEach(fn[,thisArg]) * fn:每一次执行的函数 * thisArg:可选,传入的要绑定的 this 值 */ let arr23 = [1, 2, 3, 4, 5, 6, 7] arr23.forEach((item, index) => { console.log('第', index, '个的平方是:', item * item) }) // 稀疏数组操作(未初始化的会跳过),null 不会跳过,会转为 0(有点坑) arr23 = [1, 2, 3, null, , 6, 7] arr23.forEach((item, index) => { console.log('第', index, '个的平方是:', item * item) })
注意:
即使传入的函数显示返回值,最终 forEach 也是 undefined
let arr23 = [1, 2, 3, 4, 5, 6, 7] const arr23_for = arr23.forEach((item, index) => { return item * item }) console.log(arr23_for) // undefined
2、map
map 对数组的每一种执行传入的函数,并根据函数返回值组成一个新的数组(function 默认返回 undefined)
/** * map 用于返回一个新数组,是由原数组的每一个项执行一次给定的函数返回的结果;如果函数改变了原数组的项,原数组改变; * 对于删除的、新增的、未初始化的会跳过,不执行;null 不会跳过,会转为 0 */ let arr26 = [1, 2, 3, 4, 5, 6,null, 7, 8] let arrMap = arr26.map((item) => item * 2) // 只有一句表达式,没有中括号,默认返回表达式的值 arrMap = arr26.map((item) => {item * 2}) // 返回 undefinde 组成的数组
3、find(ES6)
find 根据传入的函数,查找出第一个符合的项,并返回这个项;不存在返回 undefined
let arr28 = [1, 2, 3, 4, 5, 6, 7, 8] function getNumber(value) { return value === 5 } console.log('arr28 find 5:', arr28.find(getNumber)) // 5
4、findIndex(ES6)
findIndex 根据传入的函数,查找出第一个符合的项,并返回项索引;不存在返回 -1
let arr28 = [1, 2, 3, 4, 5, 6, 7, 8] function getNumber(value) { return value === 5 } console.log( 'findIndex 5:',arr28.findIndex(getNumber)) // 4
// 和 indexOf 区别,传入的参数不一样;这里是函数,能做的事情更多,更复杂
5、every
every 用于验证数组内的所有项是否都符合传入函数的验证
/** * 只有全部符合才返回 true ,否则 false */ let arr24 = [1, 2, 3, 4, 5, 6, 7, 8] console.log('arr24 all >0:',arr24.every((item) => item > 0)) // true
6、some
some 正好和 every 相反,只有有一个满足传入函数验证,就返回 true。
let arr24 = [1, 2, 3, 4, 5, 6, 7, 8] console.log('arr24 have >5:',arr24.some((item) => item > 5)) // true // 数组交集(可对比多个数组) const intersection = (list, ...args) => { console.log(args) return list.filter((item) => args.some((list) => list.includes(item))) } console.log(intersection([2, 1], [2, 3], [1, 4, 6])) // [2,1]
7、filter
filter 用于筛选数组中满足给定条件的项,并返回这些项的数组。
let arr25 = [1, 2, 3, 4, 5, 6, 7, 8] console.log('arr25 中大于5的项:',arr25.filter((item) => item > 5)) // 下面是一个场景的使用 // 使用 filter 创建具有非0 id 的json var arrJson = [ { id: 15 }, { id: -1 }, { id: 0 }, { id: 3 }, { id: 12.2 }, {}, { id: null }, { id: NaN }, { id: 'undefined' }, ] function isNumber(obj) { return obj !== undefined && typeof obj === 'number' && !isNaN(obj) } function filterById(item) { if (isNumber(item.id) && item.id !== 0) { return true } return false } let arrJsonNoZeroId = arrJson.filter(filterById) console.log('arrJsonNoZeroId :', arrJsonNoZeroId)
8、reduce
reduce 接收一个函数,用于汇总数组所有的项,并返回这个汇总结果。
以前一直以为这个是 ES6 的新方法,其实是挺早就有的。IE9 也支持该方法。
/** * 语法:array.reduce(callback(accumulator,currentValue[,index[,array]])[,initialValue]) * 参数: * 1、callback:传入的汇总函数 * a、accumulator:是 callback 上一次调用返回的值,或者initialValue的值 * b、currentValue:当前项 * c、当前项的索引 * d、array 当前数组 * 2、initialValue:callback 第一次调用的 accumulator 值 * a、未传值时,数组的第一个为该值,上面的回调函数会执行 length-1 次 * b、传值,会执行 length 次 */ let arr27 = [1, 2, 3, 4, 5, 6, 7, 8, 9] console.log( 'arr27 reduce +:', arr27.reduce((pre, cur) => pre + cur) ) console.log( 'arr27 reduce + 20:', arr27.reduce((pre, cur) => pre + cur, 20) ) // reduce 示例 // 1、将二维数组转为一维数组(扁平化处理) let arr27_1 = [ [1, 2], [3, 4], [5, 6], [7, 8], ] let arrReduce = arr27_1.reduce(function (a, b) { return a.concat(b) }, []) console.log('二维数组转一维数组:', arrReduce) // 2、计算每个元素出现的次数(去重也可以) let arr27_2 = ['abc', 'bcd', 'def', 'dgf', 'abc', 'def', 'abc'] function getNames(names, name) { if (name in names) { names[name]++ } else { names[name] = 1 } return names } let names = arr27_2.reduce(getNames, {}) console.log( '数组元素出现次数:', names, ' 去重后的数组:', Object.getOwnPropertyNames(names) ) // 3、根据属性,对一组对象分类 let arr27_3 = [ { name: 'abc', age: 20 }, { name: 'dbg', age: 21 }, { name: 'edv', age: 20 }, ] function groupBy(objectArr, property) { return objectArr.reduce(function (acc, curItem) { let key = curItem[property] if (acc[key]) { acc[key].push(curItem) } else { acc[key] = [curItem] } return acc }, {}) } console.log('对象数组分类:', groupBy(arr27_3, 'age'))
9、reduceRight
reduceRight 的使用和 reduce 是一样的,只是在执行的时候是从右侧开始。
10、entries(ES6)
11、keys(ES6)
12、values(ES6)
把上面三个放在一起来说。
共同点:返回的都是一个迭代器
不同点:迭代器内容不同,entries 是项和索引的键值对迭代器;keys 索引的迭代器;values 项的迭代器;
let arr29 = [1, 2, 3, 4, 5, 6, 7, 8] console.log( 'arr entries:', arr29.entries().next(), // arr entrie: { value: [ 0, 1 ], done: false } ' keys:', arr29.keys().next(), // key: { value: 0, done: false } ' values:', arr29.values().next() // value: { value: 1, done: false } )
到这里 Array 的已经写完了,后续有新功能会继续更新。