- 内置方法
- 数组方法
Array.prototype.push()Array.prototype.unshift()Array.prototype.pop()Array.prototype.shift()Array.prototype.reverse()Array.prototype.splice()Array.prototype.sort()Array.prototype.concat()Array.prototype.toString()Array.prototype.slice()Array.prototype.join()Array.prototype.indexOf()Array.prototype.lastIndexOf()Array.prototype.find()Array.prototype.findIndex()Array.prototype.sort()Array.prototype.fill()Array.prototype.includes()Array.prototype.copyWithin()Array.prototype.entries()Array.prototype.flat()Array.prototype.flatMap()Array.prototype.reduce()Array.prototype.reduceRight()Array.prototype.map()Array.prototype.filter()Array.prototype.forEach()Array.prototype.every()Array.prototype.some()Array.prototype.slice.call(arguments)Array.of()Array.from()
- 字符串方法
- 对象方法
- 数组方法
内置方法
数组方法
继承了构造函数Array的属性prototype的方法,继承原型上的方法
数组方法区分
修改原数组:
push()最后一位加,返回值都为执行了方法以后数组长度unshift()在第一位前面加,返回值都为执行了方法以后数组长度pop()返回值剪切掉最后一位shift()返回值剪切掉第一位reverse()返回值为翻转数组元素后的数组splice()返回值为修改后的数组,可以删除数组某一项,或多项,可以指定位置增加某一项sort()返回排序以后的数组,按照ASCII码来排序,传入函数参数可以自定义排序条件
新数组上的修改:
concat()返回值为整合拼接的新数组toString()返回值为类似数组结构的字符串列表,可以去掉数组的中括号数组元素变为单独的字符串slice()返回修改后的新数组,可以克隆数组,从下标元素(包括)开始截取到最后(参数1),截取的结束下标数组之前(不包括)(参数2),负值时下标元素(包括)开始截取到结束下标元素之前(不包括),还可以将类数组转为数组join()返回值为新的字符串列表,不传参返回跟toString()一样的字符串列表,默认逗号隔开,传参可以指定符号隔开split()返回值为修改后的新数组,不传参可以把字符串转为数组,参数1传入跟分隔字符一样的符号会逗号分隔数组元素,参数1传入空格会分隔所有数组元素包含分隔符号,参数2传入数字会截断下标数组元素之前(不包括)
Array.prototype.push()
将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
返回值
- 为执行了方法以后数组长度
参数
- 被添加到数组末尾的元素
参数1/返回值:
var arr = ['a', 'b', 'c'];//参数1/返回值:console.log(arr, arr.push('d'));//["a", "b", "c", "d"] 4console.log(arr, arr.push(5));//["a", "b", "c", 5] 4console.log(arr, arr.push(true));//["a", "b", "c", true] 4console.log(arr, arr.push(undefined));//["a", "b", "c", undefined] 4console.log(arr, arr.push(null));//["a", "b", "c", null] 4console.log(arr, arr.push(NaN));//["a", "b", "c", NaN] 4console.log(arr, arr.push(0));//["a", "b", "c", 0] 4console.log(arr, arr.push(false));//["a", "b", "c", false] 4console.log(arr, arr.push({}));//["a", "b", "c", {…}] 4console.log(arr, arr.push([]));//["a", "b", "c", Array(0)] 4console.log(arr, arr.push(function () {}));//["a", "b", "c", ƒ] 4console.log(arr, arr.push(new String('123')));//["a", "b", "c", String{"123"}] 4console.log(arr, arr.push(new Number('123')));//["a", "b", "c", Number{123}] 4console.log(arr, arr.push(new Boolean(true)));//["a", "b", "c", Boolean{true}] 4
参数2/返回值:
//参数2/返回值:console.log(arr, arr.push('d', 'e'));//["a", "b", "c", "d", "e"] 5console.log(arr, arr.push(4, 5));//["a", "b", "c", 4, 5] 5console.log(arr, arr.push(true, false));//["a", "b", "c", true, false] 5console.log(arr, arr.push(undefined, undefined));//["a", "b", "c", undefined, undefined] 5console.log(arr, arr.push(null, null));//["a", "b", "c", null, null] 5console.log(arr, arr.push(NaN, NaN));//["a", "b", "c", NaN, NaN] 5console.log(arr, arr.push(0, 0));//["a", "b", "c", 0, 0] 5console.log(arr, arr.push(false, false));//["a", "b", "c", false, false] 5console.log(arr, arr.push({}, {}));//["a", "b", "c", {…}, {…}] 5console.log(arr, arr.push([], []));//["a", "b", "c", Array(0), Array(0)] 5console.log(arr, arr.push(function () {}, function () {}));//["a", "b", "c", ƒ, ƒ] 5console.log(arr, arr.push(new String('123'), new String('456')));//["a", "b", "c", String{"123"}, String{"456"}] 5console.log(arr, arr.push(new Number('123'), new Number('456')));//["a", "b", "c", Number{123}, Number{456}] 5console.log(arr, arr.push(new Boolean(true), new Boolean(false)));//["a", "b", "c", Boolean{true}, Boolean{true}] 5
自己写一个push()方法
- 功能1:数组最后一位添加数组元素
- 功能2:返回执行方法以后数组长度
/*** myPush()* 将一个或多个元素添加到数组的末尾* @参数 要添加到数组开头的元素或多个元素* @返回值 执行了方法以后数组长度*/var arr = [2, 3, 4];Array.prototype.myPush = function () {//功能1:传入实参列表//循环实参列表for (var i = 0; i < arguments.length; i++) {// console.log(arguments[i]); //1 2 3//arr[索引值]数组元素 数组长度正好等于准备添加的标号//arr[arr.length] -> this[this.length]this[this.length] = arguments[i];}//功能2:返回执行方法以后数组长度return this.length;}console.log(arr.myPush(1, 2, 3)); //6console.log(arr); //[2, 3, 4, 1, 2, 3]
Array.prototype.unshift()
将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
返回值
- 为执行了方法以后数组长度
参数
- 要添加到数组开头的元素或多个元素
//push//返回值都为执行了方法以后数组长度// console.log(Array.prototype);//push最后一位加var arr = [2, 3, 4];arr.push(5); //返回值:4console.log(arr); //[2, 3, 4, 5]// arr.push(6, 7); //返回值: 6console.log(arr); //[2, 3, 4, 5, 6, 7]
//unshift//在第一位前面加var arr = [2, 3, 4];arr.unshift(1); //返回值:4console.log(arr); //[1, 2, 3, 4]
参数1/返回值:
var arr = ['a', 'b', 'c'];// //参数1/返回值:console.log(arr, arr.unshift('d'));//["d", "a", "b", "c"] 4console.log(arr, arr.unshift(5));//[5, "a", "b", "c"] 4console.log(arr, arr.unshift(true));//[true, "a", "b", "c"] 4console.log(arr, arr.unshift(undefined));//[undefined, "a", "b", "c"] 4console.log(arr, arr.unshift(null));//[null, "a", "b", "c"] 4console.log(arr, arr.unshift(NaN));//[NaN, "a", "b", "c"] 4console.log(arr, arr.unshift(0));//[0, "a", "b", "c"] 4console.log(arr, arr.unshift(false));//[false, "a", "b", "c"] 4console.log(arr, arr.unshift({}));//[{…}, "a", "b", "c"] 4console.log(arr, arr.unshift([]));//[Array(0), "a", "b", "c"] 4console.log(arr, arr.unshift(function () {}));//[ƒ, "a", "b", "c"] 4console.log(arr, arr.unshift(new String('123')));//[String{"123"}, "a", "b", "c"] 4console.log(arr, arr.unshift(new Number('123')));//[Number{123}, "a", "b", "c"] 4console.log(arr, arr.unshift(new Boolean(true)));//[Boolean{true}, "a", "b", "c"] 4
参数2/返回值:
//参数2/返回值:console.log(arr, arr.unshift('d', 'e'));//["d", "e", "a", "b", "c"] 5console.log(arr, arr.unshift(4, 5));//[4, 5, "a", "b", "c"] 5console.log(arr, arr.unshift(true, false));//[true, false, "a", "b", "c"] 5console.log(arr, arr.unshift(undefined, undefined));//[undefined, undefined, "a", "b", "c"] 5console.log(arr, arr.unshift(null, null));//[null, null, "a", "b", "c"] 5console.log(arr, arr.unshift(NaN, NaN));//[NaN, NaN, "a", "b", "c"] 5console.log(arr, arr.unshift(0, 0));//[0, 0, "a", "b", "c"] 5console.log(arr, arr.unshift(false, false));//[false, false, "a", "b", "c"] 5console.log(arr, arr.unshift({}, {}));//[{…}, {…}, "a", "b", "c"] 5console.log(arr, arr.unshift([], []));//[Array(0), Array(0), "a", "b", "c"] 5console.log(arr, arr.unshift(function () { }, function () { }));//[ƒ, ƒ, "a", "b", "c"] 5console.log(arr, arr.unshift(new String('123'), new String('456')));//[String, String, "a", "b", "c"] 5console.log(arr, arr.unshift(new Number('123'), new Number('456'))); //[Number, Number, "a", "b", "c"] 5console.log(arr, arr.unshift(new Boolean(true), new Boolean(false))); //[Boolean, Boolean, "a", "b", "c"] 5
自己写一个myUnshift()方法
- 功能1:数组第一位添加数组元素
- 功能2:返回执行方法以后数组长度
/*** unshift()* 将一个或多个元素添加到数组的开头* @参数 要添加到数组开头的元素或多个元素* @返回值 执行了方法以后数组长度*///用splice()重写原型数组的原型上的unshift()方法myUnshift()var arr = ['d', 'e', 'f'];Array.prototype.myUnshift = function () {for (var i = arguments.length - 1; i >= 0; i--) {//arr.splice(开始项的下标,剪切长度,剪切以后最后一位开始添加数据)this.splice(0, 0, arguments[i]);}//功能2:返回执行方法以后数组长度return this.length;}console.log(arr.myUnshift('a', 'b', 'c')); //6console.log(arr); //["a", "b", "c", "d", "e", "f"]
Array.prototype.pop()
从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
返回值
- 从数组中删除的元素
- 当数组为空时返回undefined
参数
- 没有
数组为空时:
var arr = [];console.log(arr, arr.pop());//[] undefined
参数1/返回值:
// //参数1/返回值:console.log(arr, arr.pop('d'));//["a", "b"] "c"console.log(arr, arr.pop(5));//["a", "b"] "c"console.log(arr, arr.pop(true));//["a", "b"] "c"console.log(arr, arr.pop(undefined));//["a", "b"] "c"console.log(arr, arr.pop(null));//["a", "b"] "c"console.log(arr, arr.pop(NaN));//["a", "b"] "c"console.log(arr, arr.pop(0));//["a", "b"] "c"console.log(arr, arr.pop(false));//["a", "b"] "c"console.log(arr, arr.pop({}));//["a", "b"] "c"console.log(arr, arr.pop([]));//["a", "b"] "c"console.log(arr, arr.pop(function () {}));//["a", "b"] "c"console.log(arr, arr.pop(new String('123')));//["a", "b"] "c"console.log(arr, arr.pop(new Number('123')));//["a", "b"] "c"console.log(arr, arr.pop(new Boolean(true)));//["a", "b"] "c"
参数2/返回值:
// //参数2/返回值:console.log(arr, arr.pop('d', 'e'));//["a", "b"] "c"console.log(arr, arr.pop(4, 5));//["a", "b"] "c"console.log(arr, arr.pop(true, false));//["a", "b"] "c"console.log(arr, arr.pop(undefined, undefined));//["a", "b"] "c"console.log(arr, arr.pop(null, null));//["a", "b"] "c"console.log(arr, arr.pop(NaN, NaN));//["a", "b"] "c"console.log(arr, arr.pop(0, 0));//["a", "b"] "c"console.log(arr, arr.pop(false, false));//["a", "b"] "c"console.log(arr, arr.pop({}, {}));//["a", "b"] "c"console.log(arr, arr.pop([], []));//["a", "b"] "c"console.log(arr, arr.pop(function () {}, function () {}));//["a", "b"] "c"console.log(arr, arr.pop(new String('123'), new String('456')));//["a", "b"] "c"console.log(arr, arr.pop(new Number('123'), new Number('456')));//["a", "b"] "c"console.log(arr, arr.pop(new Boolean(true), new Boolean(false)));//["a", "b"] "c"
自己写一个myPop()方法
/*** pop()* @参数 没有* @返回值 返回被删的最后一位数组元素* @数组本身 为空就返回undefined*/var arr = ['a', 'b', 'c', 'd'];//写一个myPop()方法Array.prototype.myPop = function () {if (this.length === 0) {return undefined;}for (var i = 0; i < this.length; i++) {var lastElm = this[this.length - 1];this.splice(-1, 1);return lastElm;}}console.log(arr.myPop()); //econsole.log(arr); //["a", "b", "c", "d"]
Array.prototype.shift()
从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
返回值
- 从数组中删除的元素;
- 如果数组为空则返回undefined 。
参数
- 没有
//pop()//pop()没有参数噢//剪切掉最后一位并返回var arr = ['a', 'b', 'c'];console.log(arr.pop()); //cconsole.log(arr); //["a", "b"]
//shift()//shift()没有参数噢//剪切掉第一位并返回//可以测试后端传入的未知数据类型var arr = ['a', 'b', 'c'];console.log(arr.shift()); //aconsole.log(arr); //["b", "c"]
数组为空时:
var arr = [];console.log(arr, arr.shift());//[] undefined
参数1/返回值:
// // //参数1/返回值:console.log(arr, arr.shift('d'));//["b", "c"] "a"console.log(arr, arr.shift(5));//["b", "c"] "a"console.log(arr, arr.shift(true));//["b", "c"] "a"console.log(arr, arr.shift(undefined));//["b", "c"] "a"console.log(arr, arr.shift(null));//["b", "c"] "a"console.log(arr, arr.shift(NaN));//["b", "c"] "a"console.log(arr, arr.shift(0));//["b", "c"] "a"console.log(arr, arr.shift(false));//["b", "c"] "a"console.log(arr, arr.shift({}));//["b", "c"] "a"console.log(arr, arr.shift([]));//["b", "c"] "a"console.log(arr, arr.shift(function () {}));//["b", "c"] "a"console.log(arr, arr.shift(new String('123')));//["b", "c"] "a"console.log(arr, arr.shift(new Number('123')));//["b", "c"] "a"console.log(arr, arr.shift(new Boolean(true)));//["b", "c"] "a"
参数2/返回值:
// // //参数2/返回值:console.log(arr, arr.shift('d', 'e'));//["b", "c"] "a"console.log(arr, arr.shift(4, 5));//["b", "c"] "a"console.log(arr, arr.shift(true, false));//["b", "c"] "a"console.log(arr, arr.shift(undefined, undefined));//["b", "c"] "a"console.log(arr, arr.shift(null, null));//["b", "c"] "a"console.log(arr, arr.shift(NaN, NaN));//["b", "c"] "a"console.log(arr, arr.shift(0, 0));//["b", "c"] "a"console.log(arr, arr.shift(false, false));//["b", "c"] "a"console.log(arr, arr.shift({}, {}));//["b", "c"] "a"console.log(arr, arr.shift([], []));//["b", "c"] "a"console.log(arr, arr.shift(function () {}, function () {}));//["b", "c"] "a"console.log(arr, arr.shift(new String('123'), new String('456')));//["b", "c"] "a"console.log(arr, arr.shift(new Number('123'), new Number('456')));//["b", "c"] "a"console.log(arr, arr.shift(new Boolean(true), new Boolean(false)));//["b", "c"] "a"
自己写一个myShift()方法
/*** myShift()* @参数 没有* @返回值 返回被删的第一位数组元素* @数组本身 为空就返回undefined*/var arr = ['a', 'b', 'c', 'd'];//myShift()方法Array.prototype.myShift = function () {if (this.length === 0) {return undefined;}for (var i = 0; i < this.length; i++) {var firstElm = this[0];this.splice(0, 1);return firstElm;}}console.log(arr.myShift()); //aconsole.log(arr); //["b", "c", "d"]
Array.prototype.reverse()
将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
返回值
- 颠倒后的原数组。
参数
- 没有
//reverse()var arr = [1, 2, 3];arr.reverse();console.log(arr); //[3, 2, 1]var arr2 = ['a', 'b', 'c'];arr2.reverse();console.log(arr2); //["c", "b", "a"]
数组为空时:
var arr = [];console.log(arr, arr.reverse());//[] []
参数1/返回值:
//参数1/返回值:console.log(arr, arr.reverse('d'));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(5));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(true));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(undefined));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(null));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(NaN));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(0));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(false));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse({}));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse([]));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(function () {}));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new String('123')));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new Number('123')));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new Boolean(true)));//["c", "b", "a"] (3) ["c", "b", "a"]
参数2/返回值:
//参数2/返回值:console.log(arr, arr.reverse('d', 'e'));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(4, 5));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(true, false));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(undefined, undefined));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(null, null));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(NaN, NaN));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(0, 0));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(false, false));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse({}, {}));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse([], []));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(function () {}, function () {}));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new String('123'), new String('456')));// ["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new Number('123'), new Number('456')));//["c", "b", "a"] (3) ["c", "b", "a"]console.log(arr, arr.reverse(new Boolean(true), new Boolean(false)));//["c", "b", "a"] (3) ["c", "b", "a"]
写一个myReverse()方法
/*** myReverse()* @参数 没有* @返回值 颠倒后的原数组*/var arr = ['a', 'b', 'c', 'd'];var arr2 = [33, 456, 21, 1, 756, 34];// myReverse()方法Array.prototype.myReverse = function () {this.sort(function (a, b) {return -1;});return this;}console.log(arr.myReverse()); //["d", "c", "b", "a"]console.log(arr2.myReverse()); //[34, 756, 1, 21, 456, 33]
Array.prototype.splice()
通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
- 删除数组某一项
- 删除数组多项
- 指定位置增加某一项
返回值
- 由被删除的元素组成的一个数组。
- 由被新增元素组成的一个数组。
- 如果没有删除元素,则返回空数组。
参数
start:开始项的下标deleteCount:剪切长度(可选)item:要添加进数组的元素(可选)
//splice//arr.splice(开始项的下标,剪切长度,剪切以后最后一位开始添加数据)var arr = ['a', 'b', 'c'];//arr.splice(下标为1, 剪切1位)arr.splice(1, 1);console.log(arr); //["a", "c"]var arr2 = ['a', 'b', 'c'];//arr.splice(下标为1, 剪切2位)arr2.splice(1, 2);console.log(arr2); //["a"]var arr3 = ['a', 'b', 'c'];//arr.splice(下标为1, 剪切2位)//注意最后一位是没有空格的arr3.splice(1, 1, 1, 2, 3);console.log(arr3); //["a", 1, 2, 3, "c"]
var arr = ['a', 'b', 'c', 'e'];//在c和e中间添加d//arr.splice(数组长度, 0, 'd');arr.splice(3, 0, 'd');console.log(arr); //["a", "b", "c", "d", "e"]
var arr = ['a', 'b', 'c', 'e'];//在c和e中间添加d// arr.splice(可以添加负值, 0, 'd')//-1代表最后一项 -2代表倒数第二项 -3.....arr.splice(-1, 0, 'd');console.log(arr); //["a", "b", "c", "d", "e"]
没有参数/返回值:
//原数组保持不变,返回空数组var arr = ['a', 'b', 'c'];console.log(arr, arr.splice());//["a", "b", "c"] []
参数1/返回值:
- 传入字符串,清空原数组,返回被删的所有数组元素
- 传入0,清空原数组,返回被删的所有数组元素
- 如传入数字超过数组长度,原数组不变,返回空数组
- 如传入数字大于0且小于数组长度,原数组保留第n位和第n+1位的元素跟传入数值n的长度相同,返回除第n位和第n+1位之外被删除的元素
- 如传为真的数值,相当于转为数值1传值,结果如数值1的结果
- 如传为假的数值,相当于转为数值0传值,结果如数值0的结果
- 如传包装类(String, Number)的数值,原数组不变,返回空数组
- 如传包装类(Boolean)的数值,根据真或假来转换为1/0,得到1/0数值的结果
var arr = ['a', 'b', 'c'];//参数1/返回值:console.log(arr, arr.splice('d'));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(-1));//["a", "b"] ["c"]console.log(arr, arr.splice(0));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(1));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(2));//["a", "b"] ["c"]console.log(arr, arr.splice(3));//["a", "b", "c"] []console.log(arr, arr.splice(4));//["a", "b", "c"] []console.log(arr, arr.splice(true));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(undefined));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(null));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(NaN));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(false));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice({}));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice([]));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(function () {}));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(new String('123')));//["a", "b", "c"] []console.log(arr, arr.splice(new Number('123')));//["a", "b", "c"] []console.log(arr, arr.splice(new Boolean(true)));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(new Boolean(false)));//[] (3) ["a", "b", "c"]
参数2/返回值:
- 传入字符串,原数组不变,返回空数组
- 参数1为元素下标(包括),参数2为删除长度
- 如删除长度为0,不做删除操作,原数组不变,返回空数组
- 如删除长度为1,删除1位元素操作,原数组为(数组长度-1)个元素,返回1个被删的下标开始截取的元素
- 如删除长度为2,删除2位元素操作,原数组为(数组长度-2)个元素,返回2个被删的下标开始截取的元素
- 如删除长度为n,删除n位元素操作,原数组为(数组长度-n)个元素,返回n个被删的下标开始截取的元素
- 如传为真的数值,相当于转为数值1传值,结果如数值1的结果
- 如传为假的数值,相当于转为数值0传值,结果如数值0的结果
- 如传包装类(String, Number)的数值,原数组不变,返回空数组
- 如传包装类(Boolean)的数值,根据真或假来转换为1/0,得到1/0数值的结果
var arr = ['a', 'b', 'c'];//参数2/返回值:console.log(arr, arr.splice('d', 'e'));//["a", "b", "c"] []console.log(arr, arr.splice(-1, -1));//["a", "b", "c"] []console.log(arr, arr.splice(-1, 0));//["a", "b", "c"] []console.log(arr, arr.splice(-1, 1));//["a", "b"] ["c"]console.log(arr, arr.splice(0, 0));//["a", "b", "c"] []console.log(arr, arr.splice(0, 1));//["b", "c"] ["a"]console.log(arr, arr.splice(0, 2));//["c"] (2) ["a", "b"]console.log(arr, arr.splice(0, 3));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(0, 4));//[] (3) ["a", "b", "c"]console.log(arr, arr.splice(1, 0));//["a", "b", "c"] []console.log(arr, arr.splice(1, 1));//["a", "c"] ["b"]console.log(arr, arr.splice(1, 2));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(1, 3));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(1, 4));//["a"] (2) ["b", "c"]console.log(arr, arr.splice(2, 0));//["a", "b", "c"] []console.log(arr, arr.splice(2, 1));//["a", "b"] ["c"]console.log(arr, arr.splice(2, 2));//["a", "b"] ["c"]console.log(arr, arr.splice(2, 3));//["a", "b"] ["c"]console.log(arr, arr.splice(2, 4));//["a", "b"] ["c"]console.log(arr, arr.splice(3, 0));//["a", "b", "c"] []console.log(arr, arr.splice(3, 1));//["a", "b", "c"] []console.log(arr, arr.splice(3, 2));//["a", "b", "c"] []console.log(arr, arr.splice(3, 3));//["a", "b", "c"] []console.log(arr, arr.splice(3, 4));//["a", "b", "c"] []console.log(arr, arr.splice(true, false));//["a", "b", "c"] []console.log(arr, arr.splice(false, false));//["a", "b", "c"] []console.log(arr, arr.splice(false, true));//["b", "c"] ["a"]console.log(arr, arr.splice(undefined, undefined));//["a", "b", "c"] []console.log(arr, arr.splice(undefined, false));//["a", "b", "c"] []console.log(arr, arr.splice(undefined, true));//["b", "c"] ["a"]console.log(arr, arr.splice(null, null));//["a", "b", "c"] []console.log(arr, arr.splice(NaN, NaN));//["a", "b", "c"] []console.log(arr, arr.splice({}, {}));//["a", "b", "c"] []console.log(arr, arr.splice([], []));//["a", "b", "c"] []console.log(arr, arr.splice(function () {}, function () {}));//["a", "b", "c"] []console.log(arr, arr.splice(new String('123'), new String('456')));//["a", "b", "c"] []console.log(arr, arr.splice(new Number('123'), new Number('456')));//["a", "b", "c"] []console.log(arr, arr.splice(new Boolean(true), new Boolean(false)));//["a", "b", "c"] []console.log(arr, arr.splice(new Boolean(true), new Boolean(true)));//["a", "c"] ["b"]
参数3/返回值:
- 传入字符串,原数组不变,返回空数组,第0位新增指定元素
- 根据下标元素(不包括)前加入新增指定元素
- 如传为真的数值,相当于转为数值1传值,结果如数值1的结果
- 如传为假的数值,相当于转为数值0传值,结果如数值0的结果
var arr = ['a', 'b', 'c'];//参数3/返回值:console.log(arr, arr.splice('d', 'e', 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(-1, -1, 'f'));//["a", "b", "f", "c"] []console.log(arr, arr.splice(-1, 0, 'f'));//["a", "b", "f", "c"] []console.log(arr, arr.splice(-1, 1, 'f'));//["a", "b", "f"] ["c"]console.log(arr, arr.splice(0, 0, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(0, 1, 'f'));//["f", "b", "c"] ["a"]console.log(arr, arr.splice(0, 2, 'f'));//["f", "c"] (2) ["a", "b"]console.log(arr, arr.splice(0, 3, 'f'));//["f"] (3) ["a", "b", "c"]console.log(arr, arr.splice(0, 4, 'f'));//["f"] (3) ["a", "b", "c"]console.log(arr, arr.splice(1, 0, 'f'));//["a", "f", "b", "c"] []console.log(arr, arr.splice(1, 1, 'f'));//["a", "f", "c"] ["b"]console.log(arr, arr.splice(1, 2, 'f'));//["a", "f"] (2) ["b", "c"]console.log(arr, arr.splice(1, 3, 'f'));//["a", "f"] (2) ["b", "c"]console.log(arr, arr.splice(1, 4, 'f'));//["a", "f"] (2) ["b", "c"]console.log(arr, arr.splice(2, 0, 'f'));//["a", "b", "f", "c"] []console.log(arr, arr.splice(2, 1, 'f'));//["a", "b", "f"] ["c"]console.log(arr, arr.splice(2, 2, 'f'));//["a", "b", "f"] ["c"]console.log(arr, arr.splice(2, 3, 'f'));//["a", "b", "f"] ["c"]console.log(arr, arr.splice(2, 4, 'f'));//["a", "b", "f"] ["c"]console.log(arr, arr.splice(3, 0, 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(3, 1, 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(3, 2, 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(3, 3, 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(3, 4, 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(true, false, 'f'));//["a", "f", "b", "c"] []console.log(arr, arr.splice(false, false, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(false, true, 'f'));//["f", "b", "c"] ["a"]console.log(arr, arr.splice(undefined, undefined, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(undefined, false, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(undefined, true, 'f'));//["f", "b", "c"] ["a"]console.log(arr, arr.splice(null, null, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(NaN, NaN, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice({}, {}, 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice([], [], 'f'));//["f", "a", "b", "c"] []console.log(arr, arr.splice(function () {}, function () {}, 'f'));//["f", "a", "b", "c"] []console.log(new String('123'));//String {"123"}console.log(arr, arr.splice(new String('13'), new String('46'), 'f'));//["a", "b", "c", "f"] []//从123位开始 删除456位,然后在这个位置增加一个fconsole.log(arr, arr.splice(new String('123'), new String('456'), 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(new Number('123'), new Number('456'), 'f'));//["a", "b", "c", "f"] []console.log(arr, arr.splice(new Boolean(true), new Boolean(false), 'f'));//1 0 f -> ["a", "f", "b", "c"] []console.log(arr, arr.splice(new Boolean(true), new Boolean(true), 'f'));//1 1 f -> ["a", "f", "c"] ["b"]
写一个splice()的函数
/*** myReverse()* @参数1 start 开始项的下标* @参数2 deleteCount 剪切长度(可选)* @参数3 item 要添加进数组的元素(可选)* @返回值1 被删除的元素组成的数组* @返回值2 被删除的元素组成的数组*/var arr = ['a', 'b', 'c', 'e'];//在c和e中间添加d// arr.splice(正值/负值, 0, 'd')// //-1代表最后一项 -2代表倒数第二项 -3.....// arr.splice(-1, 0, 'd');// console.log(arr); //["a", "b", "c", "d", "e"]function splice(arr, index) {//原理:怎么实现指定位置(相应下标)?//此时返回的是元素下标return index += index >= 0 ? 0 : arr.length;//传入3//true: index = index + 0// index = 3 + 0//传入-1//false: index = index + arr.length// index = -1 + 4//传入-3//false: index = index + arr.length// index = -3 + 4}//打印数组长度console.log(arr.length); //4//打印下标console.log(splice(arr, 3)); //3console.log(splice(arr, -1)); //3console.log(splice(arr, -3)); //1//打印元素console.log(arr[splice(arr, -3)]); //bconsole.log(arr[splice(arr, -1)]); //e
Array.prototype.sort()
对数组的元素进行排序,并返回数组。
默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
按照ASCII码来排序
返回值
- 排序后的数组。
参数
compareFunction:用来指定按某种顺序进行排列的函数。firstEl:第一个用于比较的元素。secondEl:第二个用于比较的元素。
//sort()var arr = [-1, -5, 8, 0, 2];arr.sort();console.log(arr); //升序:[-1, -5, 0, 2, 8]
var arr = ['b', 'z', 'h', 'i', 'a'];arr.sort();console.log(arr); //升序:["a", "b", "h", "i", "z"]//返回排序以后的数组console.log(arr.sort()); //["a", "b", "h", "i", "z"]
//sort()按照ASCII码来排列的var arr = [27, 49, 5, 7];arr.sort();console.log(arr); //不排序:[27, 49, 5, 7]
没有参数/返回值:
var arr = ['a', 'b', 'c'];//var arr = [];console.log(arr.sort());//["a", "b", "c"]//[]
参数1/参数2/返回值:
- 除了传入函数或
undefined,返回值传入其他参数都报错
//参数1/返回值:console.log(arr, arr.sort('d'));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(5));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(true));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(undefined));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.sort(null));// Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(NaN));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(0));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(false));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort({}));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort([]));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(function () {}));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.sort(new String('123')));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(new Number('123')));//Uncaught TypeError: The comparison function must be either a function or undefinedconsole.log(arr, arr.sort(new Boolean(true)));//Uncaught TypeError: The comparison function must be either a function or undefined
解决只排序单位的方案
//sort(函数) 函数可以自定义排序方法//1.必须携带两个参数//2.必须自定义返回值//3.如果返回值为负值,a就为前面 a < b//4.如果返回值为正值,b就为前面 a > b//5.如果返回值为0,保持不动//冒泡排序法//循环顺序//1.27比49//2.27比5//3.27比7//4.49比5//5.......//正值//27 49//5 27//7 27//5 49//7 49//5 7var arr = [27, 49, 5, 7];arr.sort(function (a, b) {//升序if (a > b) {return 1;} else {return -1;}//升序:这里也可以写为 return a - b;//降序:这里也可以写为 return b - a;//降序// if (a > b) {// return -1;// } else {// return 1;// }});console.log(arr); //[5, 7, 27, 49]// console.log(arr); //[49, 27, 7, 5]
随机排序(笔试题)
var arr = [1, 2, 3, 4, 5, 6];//随机方法//Math.ramdom() -> 0 - 1; 开区间(不包括0/1)arr.sort(function (a, b) {var rand = Math.random();//0.5之前(50%几率)//0.5之后(50%几率)//大于0.5if (rand - 0.5 > 0) {return 1;//小于0.5} else {return -1;}//也可以这样写// return Math.random() - 0.5;});console.log(arr); //每次不一样的数组
排序且数组里数据为对象(笔试题)
var arr = [//a项{son: 'Jenny',age: 18},//b项{son: 'Jone',age: 10},{son: 'Ben',age: 16},{son: 'Crytal',age: 3},{son: 'Lucy',age: 12}];//希望根据age字段排序arr.sort(function (a, b) {if (a.age > b.age) {return 1;} else {return -1;}});console.log(arr);/*** (5) [{…}, {…}, {…}, {…}, {…}]0: {son: "Crytal", age: 3}1: {son: "Jone", age: 10}2: {son: "Lucy", age: 12}3: {son: "Ben", age: 16}4: {son: "Jenny", age: 18}length: 5__proto__: Array(0)*/
根据字符长度排序
var arr = ['12345', '1', '1234', '12', '1234567'];//希望长度为准来排序arr.sort(function (a, b) {if (a.length > b.length) {return 1;} else {return -1;}//return a.length - b.length;});console.log(arr); //["1", "12", "1234", "12345", "1234567"]
Array.prototype.concat()
用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
返回新的整合数组
返回值
- 新的 Array 实例。
参数
valueN(可选):数组和/或值,将被合并到一个新的数组中。
var arr1 = ['a', 'b', 'c'];var arr2 = ['d', 'e', 'f'];var arr3 = arr1.concat(arr2);var arr4 = arr2.concat(arr1);console.log(arr1); //["a", "b", "c"]console.log(arr2); //["d", "e", "f"]console.log(arr3); //["a", "b", "c", "d", "e", "f"]console.log(arr4); //["d", "e", "f", "a", "b", "c"]
参数/返回值:
- 返回新的拼接后的数组
console.log(arr, arr.concat('e'));//["a", "b", "c"]["a", "b", "c", "e"]console.log(arr, arr.concat(5));//["a", "b", "c"]["a", "b", "c", 5]console.log(arr, arr.concat(true));//["a", "b", "c"]["a", "b", "c", true]console.log(arr, arr.concat(undefined));//["a", "b", "c"]["a", "b", "c", undefined]console.log(arr, arr.concat(null));//["a", "b", "c"]["a", "b", "c", null]console.log(arr, arr.concat(NaN));//["a", "b", "c"]["a", "b", "c", NaN]console.log(arr, arr.concat(0));//["a", "b", "c"]["a", "b", "c", 0]console.log(arr, arr.concat(false));//["a", "b", "c"]["a", "b", "c", false]console.log(arr, arr.concat({}));//["a", "b", "c"]["a", "b", "c", {…}]console.log(arr, arr.concat([]));//["a", "b", "c"]["a", "b", "c"]console.log(arr, arr.concat(function () {}));//["a", "b", "c"]["a", "b", "c", ƒ]console.log(arr, arr.concat(new String('123')));//["a", "b", "c"]["a", "b", "c", String {"123"}]console.log(arr, arr.concat(new Number(123)));//["a", "b", "c"]["a", "b", "c", Number {123}]console.log(arr, arr.concat(new Boolean(true)));//["a", "b", "c"]["a", "b", "c", Boolean {true}]
Array.prototype.toString()
返回一个字符串,表示指定的数组及其元素。
返回值
- 一个表示指定的数组及其元素的字符串。
参数
- 没有
数组上的toString()
//自动逗号分割字符串var arr = ['a', 'b', 'c'];console.log(arr.toString()); //a, b, cvar arr2 = [1, 2, 3, 4];console.log(arr2.toString()); //1, 2, 3, 4
没有参数/返回值:
var arr = ['a', 'b', 'c'];// console.log(arr, arr.toString());//["a", "b", "c"] "a,b,c"
参数/返回值:
- 不管有没有传参都返回指定数组元素的字符串
console.log(arr, arr.toString('e'));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(5));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(true));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(undefined));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(null));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(NaN));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(0));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(false));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString({}));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString([]));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(function () {}));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(new String('123')));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(new Number(123)));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString(new Boolean(true)));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString('&'));//["a", "b", "c"] "a,b,c"console.log(arr, arr.toString('-'));//["a", "b", "c"] "a,b,c"
Array.prototype.slice()
返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
返回值
- 一个含有被提取元素的新数组。
- 不传参返回新的克隆数组
参数
begin:从该索引开始提取原数组元素。
- 如果省略 begin,则 slice 从索引 0 开始。
- 如果 begin 超出原数组的索引范围,则会返回空数组。
end:在该索引处结束提取原数组元素。
- 如果 end 被省略,则 slice 会一直提取到原数组末尾。
- 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。
开区间和闭区间:
- 包含本身就叫闭区间 [start, end]
- 不包含本身就叫开区间 (start, end)
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];//克隆数组var arr1 = arr.slice();console.log(arr1); //['a', 'b', 'c', 'd', 'e', 'f']
//参数1://这里参数里的1指代下标1 从该下标(包含)开始截取到最后var arr2 = arr.slice(1);console.log(arr2); //['b', 'c', 'd', 'e', 'f']
//参数2://结束元素的下标之前(不包括)var arr3 = arr.slice(1, 3);console.log(arr3); //['b', 'c']
//负值//从该下标(包含)开始截取到结束元素的下标之前(不包括)var arr4 = arr.slice(-3, 5);console.log(arr4); //["d", "e"]var arr5 = arr.slice(-3, -2);console.log(arr5); //["d"]var arr6 = arr.slice(-3, -1);console.log(arr6); //["d", "e"]
没有参数/返回值:
var arr = ['a', 'b', 'c'];console.log(arr, arr.slice());//["a", "b", "c"] (3) ["a", "b", "c"]
当数组为空/返回值:
var arr = [];console.log(arr, arr.slice());//[] []
参数1/返回值:
- 传入参数大于等于0且小于数组长度,返回参数数值对应数量的数值元素
- 传入参数大于数值长度,返回空数组
var arr = ['a', 'b', 'c'];console.log(arr, arr.slice('e'));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(-1));//["a", "b", "c"]["c"]console.log(arr, arr.slice(0));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(1));//["a", "b", "c"] (2) ["b", "c"]console.log(arr, arr.slice(2));//["a", "b", "c"] ["c"]console.log(arr, arr.slice(3));//["a", "b", "c"] []console.log(arr, arr.slice(4));//["a", "b", "c"] []console.log(arr, arr.slice(true));//["a", "b", "c"] (2) ["b", "c"]console.log(arr, arr.slice(undefined));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(null));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(NaN));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(0));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(false));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice({}));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice([]));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(function () {}));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(new String('123')));//["a", "b", "c"] []console.log(arr, arr.slice(new Number(123)));//["a", "b", "c"] []console.log(arr, arr.slice(new Boolean(true)));//["a", "b", "c"] (2) ["b", "c"]console.log(arr, arr.slice(new Boolean(false)));//["a", "b", "c"] (3) ["a", "b", "c"]
参数2/返回值:
- 传入参数2大于参数1,返回范围为参数1下标到参数2下标的元素数组
- 传入参数2等于参数1,返回空数组
- 传入参数2小于参数1,返回空数组
- 传入参数2大于数值长度,根据参数1返回数组元素
console.log(arr, arr.slice('e', 'f'));//["a", "b", "c"] []console.log(arr, arr.slice(-1, -1));//["a", "b", "c"] []console.log(arr, arr.slice(-1, 0));//["a", "b", "c"] []console.log(arr, arr.slice(-1, 1));//["a", "b", "c"] []console.log(arr, arr.slice(-1, 2));//["a", "b", "c"] []console.log(arr, arr.slice(-1, 3));//["a", "b", "c"] ["c"]console.log(arr, arr.slice(0, 0));//["a", "b", "c"] []console.log(arr, arr.slice(0, 1));//["a", "b", "c"] ["a"]console.log(arr, arr.slice(0, 2));//["a", "b", "c"] (2) ["a", "b"]console.log(arr, arr.slice(0, 3));//["a", "b", "c"] (3) ["a", "b", "c"]console.log(arr, arr.slice(1, 0));//["a", "b", "c"] []console.log(arr, arr.slice(1, 1));//["a", "b", "c"] []console.log(arr, arr.slice(1, 2));//["a", "b", "c"] ["b"]console.log(arr, arr.slice(1, 3));//["a", "b", "c"] (2) ["b", "c"]console.log(arr, arr.slice(2, 1));//["a", "b", "c"] []console.log(arr, arr.slice(2, 2));//["a", "b", "c"] []console.log(arr, arr.slice(2, 3));//["a", "b", "c"] ["c"]console.log(arr, arr.slice(3, 3));//["a", "b", "c"] []console.log(arr, arr.slice(true, true));// ["a", "b", "c"][]console.log(arr, arr.slice(true, false));// ["a", "b", "c"][]console.log(arr, arr.slice(false, true));// ["a", "b", "c"]["a"]console.log(arr, arr.slice(undefined, undefined));//["a", "b", "c"] ["a", "b", "c"]console.log(arr, arr.slice(null, null));//["a", "b", "c"] []console.log(arr, arr.slice(NaN, NaN));//["a", "b", "c"] []console.log(arr, arr.slice(false, false));//["a", "b", "c"] []console.log(arr, arr.slice({}, {}));//["a", "b", "c"] []console.log(arr, arr.slice([], []));//["a", "b", "c"] []console.log(arr, arr.slice(function () {}, function () {}));//["a", "b", "c"] []console.log(arr, arr.slice(new String('123'), new String('456')));//["a", "b", "c"] []console.log(arr, arr.slice(new Number(123), new Number(456)));//["a", "b", "c"] []console.log(arr, arr.slice(new Boolean(true), new Boolean(false)));///["a", "b", "c"] []console.log(arr, arr.slice(new Boolean(false), new Boolean(true)));//["a", "b", "c"] ["a"]
Array.prototype.join()
将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
返回值
- 一个所有数组元素连接的字符串。
- 如果
arr.length为0,则返回空字符串。参数
separator:指定一个字符串来分隔数组的每个元素。
没有传参/返回值:
- 返回逗号隔开的字符串
var arr = ['a', 'b', 'c'];console.log(arr, arr.join());//["a", "b", "c"] "a,b,c"
数组长度为0/返回值:
var arr = [];console.log(arr, arr.join());//[] ""
参数/返回值:
- 传入
undefined, 返回逗号隔开的字符串 - 传入
[],返回没有逗号的字符串 - 传入其他字符,返回其他字符隔开的字符串
console.log(arr, arr.join('e'));//["a", "b", "c"] "aebec"console.log(arr, arr.join(5));//["a", "b", "c"] "a5b5c"console.log(arr, arr.join(true));//["a", "b", "c"] "atruebtruec"console.log(arr, arr.join(undefined));// ["a", "b", "c"] "a,b,c"console.log(arr, arr.join(null));//["a", "b", "c"] "anullbnullc"console.log(arr, arr.join(NaN));//["a", "b", "c"] "aNaNbNaNc"console.log(arr, arr.join(0));//["a", "b", "c"] "a0b0c"console.log(arr, arr.join(false));//["a", "b", "c"] "afalsebfalsec"console.log(arr, arr.join({}));//["a", "b", "c"] "a[object Object]b[object Object]c"console.log(arr, arr.join([]));//连逗号也去掉//["a", "b", "c"] "abc"console.log(arr, arr.join(function () {}));//["a", "b", "c"] "afunction () {}bfunction () {}c"console.log(arr, arr.join(new String('123')));//["a", "b", "c"] "a123b123c"console.log(arr, arr.join(new Number(123)));//["a", "b", "c"] "a123b123c"console.log(arr, arr.join(new Boolean(true)));//["a", "b", "c"] "atruebtruec"console.log(arr, arr.join('&'));//["a", "b", "c"] "a&b&c"console.log(arr, arr.join('-'));//["a", "b", "c"] "a-b-c"
Array.prototype.indexOf()
ECMAScript 2015 (6th Edition, ECMA-262)
返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];console.log(beasts.indexOf('bison'));//1// start from index 2console.log(beasts.indexOf('bison', 2));//4console.log(beasts.indexOf('giraffe'));//-1
语法
arr.indexOf(searchElement, fromIndex)
参数
searchElement:要查找的元素fromIndex:开始查找的位置。- 如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。
- 如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消
- 如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。
返回值
首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1
注意:存在重复元素的情况
indexOf()方法只返回第一个符合的元素索引
//存在重复元素的情况,indexOf()方法只返回第一个符合的元素索引var arr2 = ['a', 'b', 'a', 'c'];console.log(arr2.indexOf('a')); //0
var array = [2, 5, 9];array.indexOf(2); // 0array.indexOf(7); // -1array.indexOf(9, 2); // 2array.indexOf(2, -1); // -1array.indexOf(2, -3); // 0
找出指定元素出现的所有位置
var indices = [];var array = ['a', 'b', 'a', 'c', 'a', 'd'];var element = 'a';var idx = array.indexOf(element);while (idx != -1) {indices.push(idx);idx = array.indexOf(element, idx + 1);}console.log(indices);// [0, 2, 4]
参数1/返回值:
- 除了指定的元素,其余返回-1
- 返回指定元素的索引
- 参数为空返回-1
var arr = ['a', 'b', 'c'];console.log(arr, arr.indexOf()); //["a", "b", "c"] -1console.log(arr, arr.indexOf(1)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('abc')); //["a", "b", "c"] -1console.log(arr, arr.indexOf(true)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(false)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(undefined)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(null)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(NaN)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(0)); //["a", "b", "c"] -1console.log(arr, arr.indexOf({})); //["a", "b", "c"] -1console.log(arr, arr.indexOf([])); //["a", "b", "c"] -1console.log(arr, arr.indexOf(function () {})); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new String('abc'))); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new Number(123))); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new Boolean(true))); //["a", "b", "c"] -1console.log(arr, arr.indexOf('a')); //["a", "b", "c"] 0console.log(arr, arr.indexOf('b')); //["a", "b", "c"] 1console.log(arr, arr.indexOf('c')); //["a", "b", "c"] 2
参数2/返回值:
- 除了指定的元素,其余返回-1
var arr = ['a', 'b', 'c'];console.log(arr, arr.indexOf(1, 2)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('abc', 'bcd')); //["a", "b", "c"] -1console.log(arr, arr.indexOf(true, false)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(false, true)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(undefined, undefined)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(null, null)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(NaN, NaN)); //["a", "b", "c"] -1console.log(arr, arr.indexOf(0, 0)); //["a", "b", "c"] -1console.log(arr, arr.indexOf({}, {})); //["a", "b", "c"] -1console.log(arr, arr.indexOf([], [])); //["a", "b", "c"] -1console.log(arr, arr.indexOf(function () {}, function () {})); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new String('abc'), new String('bcd'))); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new Number(123), new Number(456))); //["a", "b", "c"] -1console.log(arr, arr.indexOf(new Boolean(true), new Boolean(false))); //["a", "b", "c"] -1
返回索引值长度小于数组长度的元素索引值
console.log(arr, arr.indexOf('a', -1)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('a', 0)); //["a", "b", "c"] 0console.log(arr, arr.indexOf('a', 1)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('a', 2)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('a', 3)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('b', -1)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('b', 0)); //["a", "b", "c"] 1console.log(arr, arr.indexOf('b', 1)); //["a", "b", "c"] 1console.log(arr, arr.indexOf('b', 2)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('b', 3)); //["a", "b", "c"] -1console.log(arr, arr.indexOf('c', -1)); //["a", "b", "c"] 2console.log(arr, arr.indexOf('c', 0)); //["a", "b", "c"] 2console.log(arr, arr.indexOf('c', 1)); //["a", "b", "c"] 2console.log(arr, arr.indexOf('c', 2)); //["a", "b", "c"] 2console.log(arr, arr.indexOf('c', 3)); //["a", "b", "c"] -1
Array.prototype.lastIndexOf()
ECMAScript 2015 (6th Edition, ECMA-262)
返回指定元素在数组中的最后一个的索引
const animals = ['Dodo', 'Tiger', 'Penguin', 'Dodo'];console.log(animals.lastIndexOf('Dodo'));//3console.log(animals.lastIndexOf('Tiger'));//1
语法
arr.lastIndexOf(searchElement, fromIndex);
参数
searchElement:被查找的元素。fromIndex:从此位置开始逆向查找。- 如果该值大于或等于数组的长度,则整个数组会被查找
- 如果为负值,将其视为从数组末尾向前的偏移
- 如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找
返回值
数组中该元素最后一次出现的索引,如未找到返回-1。
var array = [2, 5, 9, 2];var index = array.lastIndexOf(2);// index is 3index = array.lastIndexOf(7);// index is -1index = array.lastIndexOf(2, 3);// index is 3index = array.lastIndexOf(2, 2);// index is 0index = array.lastIndexOf(2, -2);// index is 0index = array.lastIndexOf(2, -1);// index is 3
查找所有元素
var indices = [];var array = ['a', 'b', 'a', 'c', 'a', 'd'];var element = 'a';var idx = array.lastIndexOf(element);while (idx != -1) {indices.push(idx);idx = (idx > 0 ? array.lastIndexOf(element, idx - 1) : -1);}console.log(indices);// [4, 2, 0];
参数1/返回值:
- 除了指定的元素,其余返回-1
- 返回指定元素的索引
- 参数为空返回-1
var arr = ['a', 'b', 'c'];console.log(arr, arr.lastIndexOf()); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(1)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('abc')); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(true)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(false)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(undefined)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(null)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(NaN)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(0)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf({})); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf([])); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(function () {})); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new String('abc'))); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new Number(123))); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new Boolean(true))); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('a')); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('b')); //["a", "b", "c"] 1console.log(arr, arr.lastIndexOf('c')); //["a", "b", "c"] 2
参数2/返回值:
- 除了指定的元素,其余返回-1
var arr = ['a', 'b', 'c'];console.log(arr, arr.lastIndexOf(1, 2)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('abc', 'bcd')); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(true, false)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(false, true)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(undefined, undefined)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(null, null)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(NaN, NaN)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(0, 0)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf({}, {})); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf([], [])); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(function () {}, function () {})); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new String('abc'), new String('bcd'))); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new Number(123), new Number(456))); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf(new Boolean(true), new Boolean(false))); //["a", "b", "c"] -1
var arr = ['a', 'b', 'c'];console.log(arr, arr.lastIndexOf('a', -1)); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('a', 0)); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('a', 1)); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('a', 2)); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('a', 3)); //["a", "b", "c"] 0console.log(arr, arr.lastIndexOf('b', -1)); //["a", "b", "c"] 1console.log(arr, arr.lastIndexOf('b', 0)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('b', 1)); //["a", "b", "c"] 1console.log(arr, arr.lastIndexOf('b', 2)); //["a", "b", "c"] 1console.log(arr, arr.lastIndexOf('b', 3)); //["a", "b", "c"] 1console.log(arr, arr.lastIndexOf('c', -1)); //["a", "b", "c"] 2console.log(arr, arr.lastIndexOf('c', 0)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('c', 1)); //["a", "b", "c"] -1console.log(arr, arr.lastIndexOf('c', 2)); //["a", "b", "c"] 2console.log(arr, arr.lastIndexOf('c', 3)); //["a", "b", "c"] 2
Array.prototype.find()
返回第一个满足条件的数组元素
find()的遍历效率是低于ES5数组扩展方法的
ESMAScript 2015 ES6
const arr = [1, 2, 3, 4, 5];// const item = arr.find(item => item > 3);const item = arr.find(function (item) {return item > 3; //返回bool})console.log(item); //4
/*** Array.prototype.find(function(item, index, arr){}, 参数2)* @item: 当前遍历的元素* @index: 当前遍历出的元素对应的下标* @arr: 当前的数组* @arguments[1]: 可选, 更改回调函数内部的this指向,默认指向window*///如果没有一个元素满足条件,返回undefinedconst arr1 = [1, 2, 3, 4, 5];const item1 = arr1.find(function (item) {return item > 5;})console.log(item1); //undefined//如果是引用值const arr2 = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'},{id: 3,name: 'wangwu'}]const item2 = arr2.find(item => item.name === 'lisi');console.log(item2); //{id: 2, name: "lisi"}//返回的元素和数组对应下标的元素是同一个引用console.log(item2 === arr2[1]); //true//回调的参数(当前遍历的元素, 当前遍历出的元素对应的下标,当前的数组)//find的第二个参数是更改回调函数内部的this指向, 非严格模式环境下,this默认指向window, 在严格模式下不传入第二个参数,this为undefind,与严格模式相统一const item3 = arr2.find(function (item, index, arr) {console.log(item); //{id: 1, name: "zhangsan"} 某一项console.log(index); //0 索引值console.log(arr); //[{…}, {…}, {…}] 数组本身console.log(this); //{a: 1}}, {a: 1})
//回调函数的返回值是布尔值,第一个返回true的对应数组元素作为find的返回值//find会遍历稀疏数组的空隙empty 具体遍历出的值,由undefined占位//ES5数组扩展方法指回遍历有值的索引const item = arr.find(function (item) {return item.id > 1;});console.log(item); //{id: 2, name: "lisi"}
//在回调函数里对其进行元素的更改是不可以的//find()是不会更改数组的//虽然新增了元素,但是find()会在第一次执行回调函数的时候,拿到这个数组最初的索引范围const arr = [1, 2, 3, 4, 5];const item = arr.find(function (item) {// console.log('Gone');// item = item + 1;arr.push(6);console.log(item); //1 2 3 4 5})console.log(arr); //[1, 2, 3, 4, 5]
const arr = [1, , 3, , , , 7, 8, 9];arr.find(function (item, index) {if (index === 0) {//删除了对应项,该项目位置不保留,在数据最后不上undefinedarr.splice(1, 1); //1 3 undefined undefined undefined 7 8 9 undefined//删除该项的值并填入undefined// delete arr[2]; //1 undefined undefined undefined undefined undefined 7 8 9// 删除该项的值并填入undefined// arr.pop(); //1 undefined 3 undefined undefined undefined 7 8 undefined}console.log(item);})
写一个myFind()
Array.prototype.myFind = function (cb) {if (this === null) {throw new TypeError('this is null');}if (typeof cb !== 'function') {throw new TypeError('Callback must be a function type');}var obj = Object(this),//保证为正整数len = obj.length >>> 0,arg2 = arguments[1],//下标step = 0;while (step < len) {var value = obj[step];if (cb.apply(arg2, [value, step, obj])) {return value;}step++;}return undefined;}const arr = [1, 2, 3, 4, 5];const item = arr.myFind(item => item > 3);console.log(item); //4
Array.prototype.findIndex()
返回第一个满足条件的数组元素的索引值
ECMASript 2015 ES6
查找元素对应的索引
const arr = [1, 2, 3, 4, 5];//返回第一个满足条件的数组对应的元素下标const idx = arr.findIndex(item => item > 2);const item = arr.find(item => item > 2);console.log(idx); //2console.log(item); //3
const arr = [1, 2, 3, 4, 5];//没有找到符合条件的元素返回 -1const idx2 = arr.findIndex(item => item > 5);console.log(idx2); //-1//数组长度为空的情况返回 -1const arr3 = [];const idx3 = arr3.findIndex(item => item > 2);console.log(idx3); //-1//稀疏数组是正常遍历空隙,空隙将会被填充为undefined//findIndex()如果回调返回了true,遍历就停止const arr4 = [, 2, , , , , , ];const idx4 = arr4.findIndex(function (item) {console.log(item); //undefined 2 1return item === 2;});console.log(idx4); //1
var arr = [, 2, , , , , , ];//遍历7次const idx = arr.findIndex(function (item) {console.log('Gone');})//遍历有值的索引项arr.some(function (item) {console.log('Gone');return false;})//1次arr.every(function (item) {console.log('Gone');return true;})//1次arr.forEach(function (item) {console.log('Gone');})//1次arr.map(function (item) {console.log('Gone');})//1次arr.filter(function (item) {console.log('Gone');})//1次arr.reduce(function (item) {console.log('Gone');}, [])//对于单纯的遍历来说,遍历空隙是没有必要的,浪费性能的,对于寻找一个Index或某一项来说,都是有意义的
/*** findIndex(function(item, index, arr){})* @argumengts[0]: function(){}* @argumengts[1]: {}* @item 遍历的当前数组元素* @index 元素对应的下标* @arr 源数组* @this 默认为window 如有第二个参数,会指向第二个参数 严格模式下this为undefined* @返回值 bool,遍历在某一次调用回调后返回true,停止*/var arr = [1, 2, 3];const idx = arr.findIndex(function (item, index, arr) {console.log(item); //1console.log(index); //0console.log(arr); //[1, 2, 3]console.log(this); //window}, {a: 1})
//回调函数内部是无法改变数组的元素值的var arr = [1, 2, 3];const idx = arr.findIndex(function (item) {item += 1;})console.log(arr); //[1, 2, 3]
//虽然增加了元素,但是遍历只会进行3次//findIndex()在第一次调用回调函数的时候确认数组的范围var arr = [1, 2, 3];const idx = arr.findIndex(function (item) {arr.push(6);console.log('Gone');console.log(item); //1 2 3})console.log(arr); //[1, 2, 3, 6, 6, 6]
var arr = [1, 2, 3];const idx = arr.findIndex(function (item, index) {// if (index === 0) {// //删除某一项// arr.splice(1, 1);// }// //仍然遍历3次// //最后一次补undefined// console.log(item); //1 3 undefined// // console.log(arr) [1, 3]// if (index === 0) {// //删除元素对应下标的值补undefined,实际数组中,对应下标变空隙empty// delete arr[1];// }// console.log(item); //1 undefined 3//console.log(arr) [1, empty, 3]if (index === 0) {//删除元素下标对应的值,补undefined,实际数组被删除了最后一项arr.pop();}console.log(item); // 1 2 undefined// console.log(arr); //[1, 2]})console.log(arr);
写一个findIndex()
var arr = [1, 2, 3];Array.prototype.myFindIndex = function (cb) {if (this == null) {throw new TypeError('this is null');}if (typeof cb !== 'function') {throw new TypeError('Callback must be a function');}var obj = Object(this),len = obj.length >>> 0,arg2 = arguments[1],step = 0;while (step < len) {var value = obj[step];if (cb.apply(arg2, [value, step, obj])) {return step;}step++;}return -1;}const idx = arr.myFindIndex(function (item, index, arr) {return item > 2;})console.log(idx); //2
Array.prototype.sort()
ES3
对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
var arr = [5, 3, 1, 2, 6, 4];var newArr = arr.sort();console.log(newArr);//[1, 2, 3, 4, 5, 6]console.log(arr);//[1, 2, 3, 4, 5, 6]//返回原数组的引用,不进行数组引用赋值//原地算法//V8引擎性能://arr.length <= 10 插入排序//arr.length > 10 快速排序//Mozilla 归并排序//Webkit c++ QSort 快速排序的理念console.log(newArr === arr); //true
/*** sort并不会按照数字大小进行排序* toString() -> 数组元素 -> 字符串* DOMString -> UTF-16字符串实现 -> 映射到String -> 构建字符串* string -> UTF-16字符串 -> String/DOMString的实例* 按照UTF-16的编码顺序来进行排序*/var arr = [5, 3, 1000, 1, 6];console.log(arr.sort());//[1, 1000, 3, 5, 6]var arr2 = ['b', 'x', 'i', 'm', 'a', 'd'];console.log(arr2.sort());//["a", "b", "d", "i", "m", "x"]var arr3 = [true, false];console.log(arr3.sort());//[false, true]
/*** 为什么要转成字符串呢?* 如果是仅限一种类型的排序的话,sort功能性太弱* 用字符串和字符编码集结合在一起形成排序规则* 可排序的范围就大了*///字符串的逐个字符进行编码位的排序var arr = ['abc', 'aba'];console.log(arr.sort());//["aba", "abc"]
//sort 一个参数(可选)//compareFunction 比较函数方法//compareFunction 自己写一个排序规则//FirElem//SecElemvar arr = [5, 1, 2, 4, 6, 3, 3];console.log(arr.sort(function (a, b) {//没有写排序规则,不进行任何排序操作//a => 1 b => 5// console.log(a, b);//return 负值 a就排在b前面//return 正数 b就排在a前面//return 0- a与b不进行排序操作// if (a < b) {// return -1;// }// if (a > b) {// return 1;// }// if (a === b) {// return 0;// }//纯数字比较// return a - b;// return b - a;// return a === b;// return -1;// return 1;// return 0;//compareFunction 必须对相同的输入有相同返回结果,结果是不确定// if (Math.random() > 0, 5) {// return 1;// }// if (Math.random() > 0, 5) {// return -1;// }}));
//非ASCII字符串排序var arr = ['我', '爱', '你'];console.log(arr.sort((a, b) => {return a.localeCompare(b);}));//["爱", "你", "我"]
//写法一var arr = ['zhangsan', 'Datian', 'Mike', 'tony'];console.log(arr.sort(function (a, b) {var _a = a.toLowerCase(),_b = b.toLowerCase();if (_a < _b) {return -1;}if (_a > _b) {return 1;}return 0;}));//["Datian", "Mike", "tony", "zhangsan"]//写法二//映射方法var arr2 = ['zhangsan', 'Datian', 'Mike', 'tony'];var newArr = arr2.map(function (item, index) {var it = {index,value: item.toLowerCase()}return it;});newArr.sort(function (a, b) {if (a.value > b.value) {return 1;}if (a.value < b.value) {return -1;}return 0;})// console.log(newArr);var res = newArr.map(function (item) {return arr2[item.index];})console.log(res);//["Datian", "Mike", "tony", "zhangsan"]
Array.prototype.fill()
ECMASript 2015 ES6
该方法实际上根据下标范围内的元素覆盖填充新的值
返回值:新修改后的数组
//Array.prototype.fill() ECMASript 2015 ES6/*** fill(value, start, end);* @value: 可选 默认全部填充undefined* @start: 可选 默认为0* @end: 可选 默认为数组长度*///[2, 4)const arr1 = [1, 2, 3, 4, 5];const newArr1 = arr1.fill('a', 2, 4);console.log(newArr1); //[1, 2, "a", "a", 5]//[2, end)//newArr就是原数组的引用const arr2 = [1, 2, 3, 4, 5];const newArr2 = arr2.fill('b', 2, 5);console.log(newArr2); //[1, 2, "b", "b", "b"]// console.log(arr === newArr); //true//[2, end)const arr3 = [1, 2, 3, 4, 5];const newArr3 = arr3.fill('c', 2);console.log(newArr3); //[1, 2, "c", "c", "c"]//[0, end)const arr4 = [1, 2, 3, 4, 5];const newArr4 = arr4.fill('d');console.log(newArr4); //["d", "d", "d", "d", "d"]//[-4 + len, -2 + len) -> [1, 3)const arr5 = [1, 2, 3, 4, 5];const newArr5 = arr5.fill('e', -4, -2);console.log(newArr5); //[1, "e", "e", 4, 5]//全部覆盖undefiedconst arr6 = [1, 2, 3, 4, 5];const newArr6 = arr6.fill();console.log(newArr6); //[undefined, undefined, undefined, undefined, undefined]//start === end//end 为开区间没办法选const arr7 = [1, 2, 3, 4, 5];const newArr7 = arr7.fill('f', 1, 1);console.log(newArr7); //[1, 2, 3, 4, 5]//start end 非数字 不变const arr8 = [1, 2, 3, 4, 5];const newArr8 = arr8.fill('g', 'a', 'b');console.log(newArr8); //[1, 2, 3, 4, 5]//start 非数字//end 数字//[0, 4]const arr9 = [1, 2, 3, 4, 5];const newArr9 = arr9.fill('g', 'a', 4);console.log(newArr9); //["g", "g", "g", "g", 5]//start end NaN 不变const arr10 = [1, 2, 3, 4, 5];const newArr10 = arr10.fill('g', NaN, NaN);console.log(newArr10); //[1, 2, 3, 4, 5]//start NaN//end 数字//[0, 4]const arr11 = [1, 2, 3, 4, 5];const newArr11 = arr11.fill('h', NaN, 4);console.log(newArr11); //["h", "h", "h", "h", 5]//start null//end null//不变const arr12 = [1, 2, 3, 4, 5];const newArr12 = arr12.fill('i', null, null);console.log(newArr12); //[1, 2, 3, 4, 5]//start undefined//end undefined//全部覆盖const arr13 = [1, 2, 3, 4, 5];const newArr13 = arr13.fill('j', undefined, undefined);console.log(newArr13); //["j", "j", "j", "j", "j"]//start 数字//end undefined//正常覆盖const arr14 = [1, 2, 3, 4, 5];const newArr14 = arr14.fill('j', 1, undefined);console.log(newArr14); //[1, "j", "j", "j", "j"]//start undefined//end 数字//正常覆盖const arr15 = [1, 2, 3, 4, 5];const newArr15 = arr15.fill('j', undefined, 4);console.log(newArr15); //["j", "j", "j", "j", 5]
无论数字,NaN,null,结果都是一样,undefined相当于没有填写
//fill()根据length填充数量//Array.prototype.fill.call(this, value);const newObj = Array.prototype.fill.call({length: 3}, 4);console.log(newObj); //{0: 4, 1: 4, 2: 4, length: 3}
//创建类数组方法function makeArrayLike(arr) {//将数组变为类数组var arrLike = {length: arr.length,push: [].push,splice: [].splice}arr.forEach(function (item, index) {[].fill.call(arrLike, item, index, index + 1);});return arrLike;}const newObj = makeArrayLike(['a','b','c','d','e']);console.log(newObj);/*** Object(5) ["a", "b", "c", "d", "e", push: ƒ, splice: ƒ]* 0: "a"* 1: "b"* 2: "c"* 3: "d"* 4: "e"* length: 5* push: ƒ push()* splice: ƒ splice()* __proto__: Object*/
写一个myFill()方法
//fill()实现过程Array.prototype.myFill = function () {var value = arguments[0] || undefined,//正负整数start = arguments[1] >> 0,end = arguments[2];if (this === null) {throw new TypeError('This is null or not defined');}//包装为对象,保证为对象类型var obj = Object(this),//保证为正整数len = obj.length >>> 0;start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);end = end === undefined ? len : end >> 0;end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);while (start < end) {obj[start] = value;start++;}return obj;}var arr = [1, 2, 3, 4, 5];const newArr = arr.myFill('a', 2, 4);console.log(newArr); //[1, 2, "a", "a", 5]
Array.prototype.includes()
ECMAScript2016 ES7
用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false
//认识这个方法/*** Array.prototype.includes()* 查询数组内是否包含某个元素* @arguments[0] target* @arguments[1] fromIndex 默认值为0* @返回值 布尔值*/const arr = [1, 2, 3, 4, 5];console.log(arr.includes(3)); //trueconsole.log(arr.includes(6)); //false
//特殊性const arr = ['1', 'a', 3, 4, 5];/*** 区分字符串数字与数字* 区分大小写*/console.log(arr.includes(1)); //falseconsole.log(arr.includes('A')); //false
//include是区分大小写的var str = 'abcde';console.log(str.includes('c')); //trueconsole.log(str.includes('f')); //falseconsole.log(str.includes('C')); //false
//includes是有第二个参数的//arr.includes(5, fromIndex)//fromIndex 默认值为0//arr.includes(5, 从下标开始)//没传参数直接返回falsevar arr = [1, 2, 3, 4, 5];console.log(arr.includes(5, 3)); //trueconsole.log(arr.includes(3, 3)); //falseconsole.log(arr.includes(2)); //trueconsole.log(arr.includes()); //falseconsole.log(arr.includes.length); //1
//负数//arr.length + (-2) 包含fromIndex//formIndex >= arr.length -> return false 不会对数组进行搜素//arr.length + (-6) = -1 < 0 整个数组都会搜素 从0开始console.log(arr.includes(3, -3)); //trueconsole.log(arr.includes(3, 5)); //falseconsole.log(arr.includes(3, -6)); //true
//零值相等 SAME-VALUE-ZEROvar arr = [0, 1, 2, 3, 4, 5];console.log(arr.includes(0)); //trueconsole.log(arr.includes(-0)); //trueconsole.log(arr.includes(+0)); //true
//除了数组和字符串,其他类型的数据使用includes//includes 通用方法 调用者不一定非要是数组和对象 -> this 不一定是数组和对象//包装一下1console.log(Array.prototype.includes.call(1, 'a')); //falseconsole.log([].includes.call(true, 'a')); //falseconsole.log([].includes.call({0: 'a'}, 'a')); //falseconsole.log([].includes.call({0: 'a',length: 1}, 'a')); //true
实现myIncludes()方法
Array.prototype.myIncludes = function (value) {if (this == null) {throw new TypeError('this is null');}var fromIndex = arguments[1],obj = Object(this),len = obj.length >>> 0;if (len === 0) {return false;}//位或//如果为undefined 赋值为0fromIndex = fromIndex | 0;fromIndex = Math.max(fromIndex >= 0 ? fromIndex : len + fromIndex, 0);while (fromIndex < len) {if (obj[fromIndex] === value) {return true;}fromIndex++;}return false;}var arr = [1, 2, 3, 4, 5];console.log(arr.myIncludes(5, 3)); //trueconsole.log(arr.myIncludes(3, 3)); //falseconsole.log(arr.myIncludes(2)); //trueconsole.log(arr.myIncludes()); //falseconsole.log(arr.myIncludes.length); //1console.log(arr.myIncludes(3, -3)); //trueconsole.log(arr.myIncludes(3, 5)); //falseconsole.log(arr.myIncludes(3, -6)); //true
Array.prototype.copyWithin()
浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。
//ES2015(ES6)//arr.copyWithin(target, start, end)//替换下标为0的元素//从3-4替换第0位元素//1.3-4 [3, 4)const arr = [1, 2, 3, 4, 5];const newArr = arr.copyWithin(0, 3, 4);console.log(newArr); //[4, 2, 3, 4, 5]//2.target 从 ...//3.end > len - 1 取到末尾const arr2 = [1, 2, 3, 4, 5];const newArr2 = arr2.copyWithin(0, 3, 5);console.log(newArr2); //[4, 5, 3, 4, 5]//4.target > len - 1 不发生任何替换const arr3 = [1, 2, 3, 4, 5];const newArr3 = arr3.copyWithin(5, 1, 5);console.log(newArr3); //[1, 2, 3, 4, 5]//5.target > start 正常替换const arr4 = [1, 2, 3, 4, 5];const newArr4 = arr4.copyWithin(3, 1, 3);console.log(newArr4); //[1, 2, 3, 2, 3]//6.start或end是负数 start + len ; end + len(0 2 4)const arr5 = [1, 2, 3, 4, 5];const newArr5 = arr5.copyWithin(0, -3, -1);console.log(newArr5); //[3, 4, 3, 4, 5]//7.如果没有start 取整个数组的元素//copyWithin()是不改变数组长度const arr6 = [1, 2, 3, 4, 5];const newArr6 = arr6.copyWithin(3);console.log(newArr6); //[1, 2, 3, 1, 2]//7.返回的是原数组引用//copyWithin()是不改变数组长度const arr7 = [1, 2, 3, 4, 5];const newArr7 = arr7.copyWithin(1, 3);console.log(newArr7); //[1, 4, 5, 4, 5]console.log(newArr7 === arr7); //true//memcpy -> 移动数组元素//过程一 复制元素集合//过程二 全选target及符合复制的元素集合的长度的元素再粘贴
var obj = {0: 1,1: 2,2: 3,3: 4,4: 5,length: 5}//对象下没有copyWithin()方法,用call()方法借用//this不一定非要指向数组, 可以指向一个对象const newObj = [].copyWithin.call(obj, 0, 2, 4);console.log(newObj);//同一引用console.log(obj === newObj); //true/*** console.log(newObj);* {2: 3,3: 4,2: 3,3: 4,4: 5,length: 5}*/
写一个myCopyWithin()方法
/*** @target参数: 必填* @start参数: 选填* @end参数: 选填*/Array.prototype.myCopyWithin = function (target) {if (this == null) {throw new TypeError('this is null or not defined');}//包装一下this防止是原始值var obj = Object(this),//保证length为正整数 右位移为0len = obj.length >>> 0,start = arguments[1],end = arguments[2],count = 0,//方向dir = 1;//保证target为正整数target = target >> 0;//target 小于0 找最大值 大于等于0 取最小值//Math.max(len + target, 0) 谁大取谁target = target < 0 ? Math.max(len + target, 0) : Math.min(target, len);//保证start存在,存在给正整数,否则为0start = start ? start >> 0 : 0;//负值找最大值start = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);//保证end存在,存在给正整数,否则为0end = end ? end >> 0 : len;//负值找最大值end = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);//取值范围count = Math.min(end - start, len - target);if (start < target && target < (start + count)) {dir = -1;start += count - 1;target += count - 1;}while (count > 0) {if (start in obj) {obj[target] = obj[start];} else {delete obj[target];}start += dir;target += dir;count--;}return obj;}const arr = [1, 2, 3, 4, 5];const newArr = arr.myCopyWithin(0, 3, 4);console.log(newArr); //[4, 2, 3, 4, 5]
Array.prototype.entries()
返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
ES6新增
const arr = [1, 2, 3, 4, 5];const _ = arr.entries();console.log(_);//Array Iterator {} 返回的是数组的迭代器对象const it = arr.entries();//next() -> {value:[index, item], done: ?}console.log(it.next()); //{value: [0, 1], done: false}console.log(it.next()); //{value: [1, 2], done: false}console.log(it.next()); //{value: [2, 3], done: false}console.log(it.next()); //{value: [3, 4], done: false}console.log(it.next()); //{value: [4, 5], done: false}console.log(it.next()); //{value: undefined, done: true}
//for in 遍历对象for (let key in o) {console.log(key, o[key]); //a 1 b 2 c 3}//for of 遍历数组for (let v of arr) {console.log(v); //1 2 3 4 5}
//遍历数组迭代的对象for (let v of it) {console.log(v); //1 2 3 4 5}/*** console.log(v):* (2) [0, 1]* (2) [1, 2]* (2) [2, 3]* (2) [3, 4]* (2) [4, 5]*/
//拿到下标和对应的值for (let collection of it) {const [i, v] = collection;console.log(i, v);}/*** console.log(i, v):* 0 1* 1 2* 2 3* 3 4* 4 5*/
//数组实际上就是一个特殊的对象,key键名是一个从0开始有序递增的数字//按顺序对应上数组的每一个元素//类数组var o = {0: 1,1: 2,2: 3,length: 3,[Symbol.iterator]: Array.prototype[Symbol.iterator]}//通过属性是否继承了Array.prototype[Symbol.iterator]//for of 可以遍历可迭代对象for (let v of o) {console.log(v); //Uncaught TypeError: o is not iterable 不是可迭代对象console.log(v); //加上[Symbol.iterator]属性后遍历出 1 2 3}
//next()运行案例const arr = [1, 2, 3, 4, 5];const it = arr.entries();var newArr = [];for (var i = 0; i < arr.length + 1; i++) {var item = it.next();// console.log(item.value);!item.done && (newArr[i] = item.value);}console.log(newArr);/*** console.log(newArr):* (5) [Array(2), Array(2), Array(2), Array(2), Array(2)]* 0: (2) [0, 1]* 1: (2) [1, 2]* 2: (2) [2, 3]* 3: (2) [3, 4]* 4: (2) [4, 5]* length: 5* __proto__: Array(0)*/
//二维数组排序案例const newArr = [[56, 23],[56, 34, 100, 1],[123, 234, 12]];function sortArr(arr) {//生成一个迭代器对象var _it = arr.entries(),_doNext = true;while (_doNext) {var _r = _it.next();if (!_r.done) {_r.value[1].sort(function (a, b) {return a - b;});_doNext = true;} else {_doNext = false;}}return arr;}console.log(sortArr(newArr));/*** (3) [Array(2), Array(4), Array(3)]* 0: (2) [23, 56]* 1: (4) [1, 34, 56, 100]* 2: (3) [12, 123, 234]* length: 3* __proto__: Array(0)*/
Array.prototype.flat()
ECMAScript2019
按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
参数情况:
//flag 扁平化 多维数组 -> 一维数组//针对数组//[1,2,3,4,5,[6,7]]const arr = [0, 1, [2, 3], 4, 5];const newArr = arr.flat();console.log(newArr); //[0, 1, 2, 3, 4, 5]//返回一个新的数组,将二维数组转化成一维数组console.log(newArr === arr); //false
//三维数组//参数:结构深度 默认为1,向数组内部深入一层//flat()默认情况下参数是1 -> 向内深入一层const arr = [0, 1, [2, [3, 4], 5], 6];const newArr = arr.flat(1);console.log(newArr); //[0, 1, 2, Array(2), 5, 6]//flat()参数是2 -> 向内深入2层const arr2 = [0, 1, [2, [3, 4], 5], 6];const newArr2 = arr2.flat(2);console.log(newArr2); //[0, 1, 2, 3, 4, 5, 6]
//多维数组//参数: Infinity 正无穷 深度结构 无穷大的设置const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];const newArr = arr.flat(Infinity);console.log(newArr); //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//参数为负数情况不做任何扁平化处理的const arr = [0, 1, [2, [3, 4], 5], 6];const newArr = arr.flat(-2);console.log(newArr); //[0, 1, Array(3), 6]
//数字字符串 -> Number() -> 数字类型const arr = [0, 1, [2, [3, 4], 5], 6];const newArr = arr.flat('a');console.log(newArr); //[0, 1, Array(3), 6]const arr2 = [0, 1, [2, [3, 4], 5], 6];const newArr2 = arr2.flat('3');console.log(newArr2); //[0, 1, 2, 3, 4, 5, 6]
//参数为负数0,不做任何扁平化处理的,数字必须从1开始填写,直到Infinityconst arr = [0, 1, [2, [3, 4], 5], 6];const newArr = arr.flat(0);console.log(newArr); //[0, 1, Array(3), 6]
//bool -> Number() -> 数字类型const arr = [0, 1, [2, [3, 4], 5], 6];const newArr = arr.flat(false); //0console.log(newArr); //[0, 1, Array(3), 6]//bool -> Number() -> 数字类型const arr2 = [0, 1, [2, [3, 4], 5], 6];const newArr2 = arr2.flat(true); //1console.log(newArr2); //[0, 1, 2, Array(2), 5, 6]
稀疏数组情况:
//剔除所有的数组空隙emptyconst arr = [1, , [2, , [3, 4, , 5, , , 6, [7, , , 8, 9, , [0]]]]];const newArr = arr.flat(Infinity);console.log(newArr); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
var a = 1,b = [2, 3],c = [3, 4];//concat 是可以放入多个数组元素或者其他数组const newArr = b.concat(a);console.log(newArr); //[2, 3, 1]const newArr2 = b.concat(a, c);console.log(newArr2); //[2, 3, 1, 3, 4]
浅扁平化实现:
//浅扁平化实现const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];//reduce() 归纳function shallowFlat(arr) {return arr.reduce(function (prev, current) {return prev.concat(current);}, [])}console.log(shallowFlat(arr));//[0, 1, 2, Array(3)]
const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];function shallowFlat(arr) {//展开数组return [].concat(...arr);}console.log(shallowFlat(arr));//[0, 1, 2, Array(3)]
深扁平化实现:
//方法一//reduce + concat + isArray + 递归const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];Array.prototype.deepFlat = function () {var arr = this,deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity;return deep > 0 ? arr.reduce(function (prev, current) {return prev.concat(Array.isArray(current) ? current.deepFlat(deep - 1) : current)}, []) : arr;}console.log(arr.deepFlat(Infinity));// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//方法二//forEach + isArray + push + 递归const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];Array.prototype.deepFlat = function () {var arr = this,deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity,res = [];(function _(arr, deep) {//数组扩展方法是会剔除emptyarr.forEach(function (item) {if (Array.isArray(item) && deep > 0) {//递归_(item, deep - 1);} else {res.push(item);}})})(arr, deep);return res;}console.log(arr.deepFlat(Infinity));// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//方法三//for of + isArray + push 去掉emptyconst arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];Array.prototype.deepFlat = function () {var arr = this,deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity,res = [];(function _(arr, deep) {for (var item of arr) {if (Array.isArray(item) && deep > 0) {_(item, deep - 1);} else {//判断empty 用void 0item !== void 0 && res.push(item);}}})(arr, deep);return res;}console.log(arr.deepFlat(Infinity));// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//方法四//stack pop + push (重要)const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];Array.prototype.deepFlat = function () {var arr = this,stack = [...arr],res = [];//直到stack.length = 0while (stack.length) {//返回删除的最后一项const popItem = stack.pop();if (Array.isArray(popItem)) {//如果为数组//展开放入数组里stack.push(...popItem);} else {res.push(popItem);}}return res.reverse();}console.log(arr.deepFlat(Infinity));// // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//方法五//纯递归const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];Array.prototype.deepFlat = function () {var arr = this,res = [];(function _(arr) {arr.forEach(function (item) {if (Array.isArray(item)) {_(item);} else {res.push(item);}})})(arr);return res;}console.log(arr.deepFlat(Infinity));// // // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
//方法六//生成器函数const arr = [0, [1, 2, [3, 4, [5, 6, [7, 8, [9]]]]]];function* deepFlat(arr) {for (var item of arr) {if (Array.isArray(item)) {yield* deepFlat(item);} else {yield item;}}}//平铺执行结果console.log([...deepFlat(arr)]);// // // // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array.prototype.flatMap()
ECMAScript 2020
首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。
//flat + map === flatMapconst arr = ['123', '456', '789'];// 希望的格式:['1','2','3','4','5',...];//返回数组为二维数组const newArr = arr.map(function (item) {// console.log(item); //123 456 789// console.log(item.split(''));//["1", "2", "3"] ["4", "5", "6"] ["7", "8", "9"]return item.split('');});console.log(newArr);//[Array(3), Array(3), Array(3)]//变为一维数组const newArr2 = arr.map(function (item) {// console.log(item); //123 456 789// console.log(item.split(''));//["1", "2", "3"] ["4", "5", "6"] ["7", "8", "9"]return item.split('');}).flat();console.log(newArr2);//["1", "2", "3", "4", "5", "6", "7", "8", "9"]
// flatMap()//遍历 + 扁平化//map + flat//效率更高,一体化完成//ECMA - 262 / MDNconst newArr = arr.flatMap(function (item) {// console.log(item); //123 456 789// console.log(item.split(''));//["1", "2", "3"] ["4", "5", "6"] ["7", "8", "9"]return item.split('');})console.log(newArr);//["1", "2", "3", "4", "5", "6", "7", "8", "9"]
//返回值为新的数组console.log(newArr === arr); //false
/*** flatMap(function(item, index, arr){})* @arguments[0] 参数一为回调函数* @arguments[1] 参数二可以更改回调内this指向* @item 当前遍历的元素* @index 当前遍历的元素在数组中对应的下标* @arr 数组本身* @this 默认指向window 严格模式为undefined*/const newArr = arr.flatMap(function (item, index, arr) {console.log(this);}, {a: 1})
const arr = ['My name\'s kevin', 'I am 30', 'years old.'];const newArr = arr.map(function (item) {return item.split(' ');})console.log(newArr);/*** (3) [Array(3), Array(3), Array(2)]* 0: (3) ["My", "name's", "kevin"]* 1: (3) ["I", "am", "30"]* 2: (2) ["years", "old."]* length: 3* __proto__: Array(0)*/const newArr2 = arr.flatMap(function (item) {return item.split(' ');})console.log(newArr2);//["My", "name's", "kevin", "I", "am", "30", "years", "old."]
//希望只要遇到负数就会跟前一位相加,并且把运算的过程的字符串打印出来const arr = [1, -2, -3, 5, 8, -9, 6, 7, 0];const newArr = arr.flatMap(function (item, index) {if (item < 0 && index >= 1) {return [item, `${item}+${arr[index - 1]}=${item + arr[index - 1]}`];}return item;})console.log(newArr);//[1, -2, "-2+1=-1", -3, "-3+-2=-5", 5, 8, -9, "-9+8=-1", 6, 7, 0]
写一个myFlatMap()方法
const arr = ['123', '456', '789'];Array.prototype.myFlagMap = function (cb) {if (typeof cb !== 'function') {throw new TypeError('Callback must be a function');}var arr = this,//有可能有第二个参数arg2 = arguments[1],res = [],item;for (var i = 0; i < arr.length; i++) {item = cb.apply(arg2, [arr[i], i, arr]);item && res.push(item);}return res.flat();}const newArr = arr.myFlagMap(function (item) {return item.split('');})console.log(newArr);//["1", "2", "3", "4", "5", "6", "7", "8", "9"]
Array.prototype.reduce()
归纳函数,数据筛选和归纳,划分,代码更易于维护和更新。
对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
const array1 = [1, 2, 3, 4];const reducer = (accumulator, currentValue) => accumulator + currentValue;// 1 + 2 + 3 + 4console.log(array1.reduce(reducer));// expected output: 10// 5 + 1 + 2 + 3 + 4console.log(array1.reduce(reducer, 5));// expected output: 15
reducer 函数接收4个参数:
- Accumulator (acc) (累计器)
- Current Value (cur) (当前值)
- Current Index (idx) (当前索引)
- Source Array (src) (源数组)
您的 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。
语法
arr.reduce(callback(accumulator, currentValue, index, array), initialValue);
参数
callback:执行数组中每个值 (如果没有提供initialValue则第一个值除外)的函数accumulator:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值currentValue:数组中正在处理的元素index:可选,数组中正在处理的当前元素的索引(如果提供了initialValue,则起始索引号为0否则从索引1起始)arrar:可选,调用reduce()的数组
initialValue:可选,作为第一次调用callback函数时的第一个参数的值。- 如果没有提供初始值,则将使用数组中的第一个元素。
- 在没有初始值的空数组上调用 reduce 将报错。
返回值
函数累计处理的结果
描述
reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:
accumulator 累计器currentValue 当前值currentIndex 当前索引array 数组
回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:
- 如果调用
reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值; - 如果没有提供
initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。 - 如果数组为空且没有提供
initialValue,会抛出TypeError - 如果数组仅有一个元素(无论位置如何)并且没有提供
initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。
reduce() 如何运行
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){return accumulator + currentValue;});//由`reduce`返回的值将是最后一次回调返回值(10)。
callback 被调用四次,每次调用的参数和返回值如下表:
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
|---|---|---|---|---|---|
| first call | 0 |
1 |
1 |
[0, 1, 2, 3, 4] |
1 |
| second call | 1 |
2 |
2 |
[0, 1, 2, 3, 4] |
3 |
| third call | 3 |
3 |
3 |
[0, 1, 2, 3, 4] |
6 |
| fourth call | 6 |
4 |
4 |
[0, 1, 2, 3, 4] |
10 |
使用箭头函数来代替完整的函数。 下面的代码将产生与上面的代码相同的输出:
[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr );
提供一个初始值作为reduce()方法的第二个参数,以下是运行过程及结果:
[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {return accumulator + currentValue}, 10)//这种情况下reduce()返回的值是20。
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
|---|---|---|---|---|---|
| first call | 10 |
0 |
0 |
[0, 1, 2, 3, 4] |
10 |
| second call | 10 |
1 |
1 |
[0, 1, 2, 3, 4] |
11 |
| third call | 11 |
2 |
2 |
[0, 1, 2, 3, 4] |
13 |
| fourth call | 13 |
3 |
3 |
[0, 1, 2, 3, 4] |
16 |
| fifth call | 16 |
4 |
4 |
[0, 1, 2, 3, 4] |
20 |
示例
数组里所有值的和
var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {return accumulator + currentValue;}, 0);// 和为 6//箭头函数的形式var total = [ 0, 1, 2, 3 ].reduce(( acc, cur ) => acc + cur,0);
累加对象数组里的值
//要累加对象数组中包含的值,必须提供初始值,以便各个item正确通过你的函数。var initialValue = 0;var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {return accumulator + currentValue.x;},initialValue)console.log(sum) // logs 6//箭头函数形式var initialValue = 0;var sum = [{x: 1}, {x:2}, {x:3}].reduce((accumulator, currentValue) => accumulator + currentValue.x,initialValue);console.log(sum) // logs 6
将二维数组转化为一维
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {return a.concat(b);},[]);// flattened is [0, 1, 2, 3, 4, 5]//箭头函数形式var flattened = [[0, 1], [2, 3], [4, 5]].reduce(( acc, cur ) => acc.concat(cur),[]);
计算数组中每个元素出现的次数
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];var countedNames = names.reduce(function (allNames, name) {if (name in allNames) {allNames[name]++;}else {allNames[name] = 1;}return allNames;}, {});// countedNames is:// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
按属性对object分类
var people = [{ name: 'Alice', age: 21 },{ name: 'Max', age: 20 },{ name: 'Jane', age: 20 }];function groupBy(objectArray, property) {return objectArray.reduce(function (acc, obj) {var key = obj[property];if (!acc[key]) {acc[key] = [];}acc[key].push(obj);return acc;}, {});}var groupedPeople = groupBy(people, 'age');// groupedPeople is:// {// 20: [// { name: 'Max', age: 20 },// { name: 'Jane', age: 20 }// ],// 21: [{ name: 'Alice', age: 21 }]// }
使用扩展运算符和initialValue绑定包含在对象数组中的数组
// friends - 对象数组// where object field "books" - list of favorite booksvar friends = [{name: 'Anna',books: ['Bible', 'Harry Potter'],age: 21}, {name: 'Bob',books: ['War and peace', 'Romeo and Juliet'],age: 26}, {name: 'Alice',books: ['The Lord of the Rings', 'The Shining'],age: 18}];// allbooks - list which will contain all friends' books +// additional list contained in initialValuevar allbooks = friends.reduce(function(prev, curr) {return [...prev, ...curr.books];}, ['Alphabet']);// allbooks = [// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace',// 'Romeo and Juliet', 'The Lord of the Rings',// 'The Shining'// ]
数组去重
let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']let myOrderedArray = myArray.reduce(function (accumulator, currentValue) {if (accumulator.indexOf(currentValue) === -1) {accumulator.push(currentValue)}return accumulator}, [])console.log(myOrderedArray)
let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4];let result = arr.sort().reduce((init, current) => {if(init.length === 0 || init[init.length-1] !== current) {init.push(current);}return init;}, []);console.log(result); //[1,2,3,4,5]
扁平化数组里面对象结构
//利用reduce扁平化数组里面对象结构var data = [{value: "1,2"}, {value: "3"}, {value: "4,5"}];var res = data.reduce(function (prev, elem) {//数据操作// console.log(elem.value); //1,2 3 4,5//数组每一项的值进行split字符串以逗号方式拆分//并让空数组prev用concat方法拼接在一起return prev.concat(elem.value.split(','));}, []);console.log(res);//["1", "2", "3", "4", "5"]
分析reduce
/*** 分析reduce()* 结论1:第一次return prev参数(初始值为空数组(initialValue参数提供)),* 结论2:每一次遍历data数据,都可以对prev数组进行数据操作* 结论3:归纳函数是在条件范围之内往容器里扔东西且让容器成为一个新的东西*/var initialValue = [];courseData.reduce(function (prev, elem, index, arr) {//情况1:prev值打印一次 后面打印为undefined// console.log(prev);// console.log(arr);//情况2:证明prev与initialValue是否同一个东西 结果是true// console.log(prev === initialValue);//true X 1 / false X 6(因为后面为undefined)//情况3:证明reduce每次遍历时回调函数里必须return prev//侧面说明reduce程序靠返回prev才能继续执行下去//每次return prev; prev里才有值// console.log(prev); //打印7个[]// return prev;}, initialValue);
案例1
//应用1:把courseData里的某一字段(course)数据归纳到一个数组中//说明每次数据进行reduce的时候可以操作prev,然后把操作后的prev return 出去//1.遍历数据var nArr = courseData.reduce(function (prev, elem, index, arr) {//2.操作prevprev.push(elem.course);//3.return prev出去return prev;}, initialValue);console.log(nArr);//["前端开发之企业级深度JavaScript特训课【JS++前端】", "WEB前端工程师就业班之深度JS DOM+讲师辅导-第3期【JS++前端】", "前端开发之企业级深度HTML特训课【JS++前端】", "前端开发之企业级深度CSS特训课【JS++前端】", "前端就业班VueJS+去哪儿网+源码课+讲师辅导-第3期【JS++前端】", "前端就业班ReactJS+新闻头条实战+讲师辅导-第3期【JS++前端】", "WEB前端开发工程师就业班-直播/录播+就业辅导-第3期【JS++前端】"]
案例2
//应用2:把免费课程都筛选到一个数组中//跟filter区别:filter为过滤方式,reduce为归纳的方式//过滤的方式是返回布尔值true就放,false就扔掉//归纳是在条件范围之内往容器里扔东西且让容器成为一个新的东西var nArr1 = courseData.reduce(function (prev, elem, index, arr) {if (elem.is_free === '1') {prev.push(elem);}return prev;}, initialValue);console.log(nArr1);/*** console.log(nArr1):* (3) [{…}, {…}, {…}]* 0: {id: "1", course: "前端开发之企业级深度JavaScript特训课【JS++前端】", classes: "19", teacher: "小野", img: "ecmascript.jpg", …}* 1: {id: "3", course: "前端开发之企业级深度HTML特训课【JS++前端】", classes: "3", teacher: "小野", img: "html.jpg", …}* 2: {id: "4", course: "前端开发之企业级深度CSS特训课【JS++前端】", classes: "5", teacher: "小野", img: "css.jpg", …}* length: 3*/
案例3
//应用3//把cookies信息整理为对象格式的数据//期待格式// {// BAIDUID: '04B95FD81DCE5E4D8FE723A4F46FC20A',// PSTM: '1603714330',// ...// }//cookies数据var cookieDatas = 'BIDUPSID=04B95FD81DCE5E4D68904041B9D32D3B; PSTM=1603714330; BAIDUID=04B95FD81DCE5E4D8FE723A4F46FC20A:FG=1; PANWEB=1; BDUSS=m9jaG5zdEw5c2Fuay1MOWtHQUV-RlNjZFpyeFJQM3lDSkFuMkdROXVVOE9WNzVmRVFBQUFBJCQAAAAAAAAAAAEAAAAX6jgcMjczMTIyMTg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Kll8OypZfN; BDUSS_BFESS=m9jaG5zdEw5c2Fuay1MOWtHQUV-RlNjZFpyeFJQM3lDSkFuMkdROXVVOE9WNzVmRVFBQUFBJCQAAAAAAAAAAAEAAAAX6jgcMjczMTIyMTg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Kll8OypZfN; MCITY=-138:'//以 ; 分割数组元素var cookiesArr = cookieDatas.split(';')// console.log(cookiesArr);//["BIDUPSID=04B95FD81DCE5E4D68904041B9D32D3B", " PSTM=1603714330", " BAIDUID=04B95FD81DCE5E4D8FE723A4F46FC20A:FG=1", " PANWEB=1",...]//使用reduce归纳 以 = 整理的数组var cookieObj = cookiesArr.reduce(function (prev, elem, index, arr){// = 号 分割每一项数组元素里的数据var item = elem.split('=');// console.log(item);//["BIDUPSID", "04B95FD81DCE5E4D68904041B9D32D3B"] ...//这里prev是初始值{}prev[item[0]] = item[1];return prev;}, {});console.log(cookieObj);/*** console.log(cookieObj);:* {* BIDUPSID: "04B95FD81DCE5E4D68904041B9D32D3B",* " PSTM": "1603714330", " BAIDUID": "04B95FD81DCE5E4D8FE723A4F46FC20A:FG",* " PANWEB": "1",* "BDUSS":"m9jaG5zdEw5c2Fuay1MOWtHQUV-RlNjZFpyeFJQM3lDSkFuMkd…AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Kll8OypZfN",* …* }*/
重写
/*** 重写reduce()* 归纳函数,对数据进行筛选,归纳* 默认改变不了this的指向,但自己写的话新增改变this指向(参数3)** 基本形态:* [].reduce(function(elem,index,arr){});** 改造形态:* [].reduce(function(prev,elem,index,arr){},initialValue);** 进行数据过滤* @返回值 不return 为 undefined* @返回值 返回操作后(归纳,筛选)得到的数组** @参数1: 回调函数* @参数2: initialValue(必填)* @回调函数参数1: 操作后返回的数组(第一次默认为[],如有initialValue,用initialValue)* @回调函数参数2: 元素* @回调函数参数3: 索引(可选)* @回调函数参数4: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装myReduceArray.prototype.myReduce = function (fn, initialValue) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arguments[2], 没传指向windowarg2 = arguments[2] || window;for (var i = 0; i < len; i++) {item = deepClone(arr[i]);//每遍历一次数组,执行一次回调函数fn//每一次调用fn的返回值就是initialValueinitialValue = fn.apply(arg2, [initialValue, arr[i], i, arr]);//因为第三参数需要改变this指向所以改写为fn.apply(this,[initialValue,参数2,参数3,参数4])}//这里记得return initialValue 否则程序无法正常执行且报错return initialValue;}//使用myReduce//cookies数据var cookieDatas = 'BIDUPSID=04B95FD81DCE5E4D68904041B9D32D3B; PSTM=1603714330; BAIDUID=04B95FD81DCE5E4D8FE723A4F46FC20A:FG=1; PANWEB=1; BDUSS=m9jaG5zdEw5c2Fuay1MOWtHQUV-RlNjZFpyeFJQM3lDSkFuMkdROXVVOE9WNzVmRVFBQUFBJCQAAAAAAAAAAAEAAAAX6jgcMjczMTIyMTg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Kll8OypZfN; BDUSS_BFESS=m9jaG5zdEw5c2Fuay1MOWtHQUV-RlNjZFpyeFJQM3lDSkFuMkdROXVVOE9WNzVmRVFBQUFBJCQAAAAAAAAAAAEAAAAX6jgcMjczMTIyMTg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7Kll8OypZfN; MCITY=-138:'//以 ; 分割数组元素var cookiesArr = cookieDatas.split(';');// //使用reduce归纳 以 = 整理的数组var cookieObj = cookiesArr.myReduce(function (prev, elem) {// = 号 分割每一项数组元素里的数据var item = elem.split('=');// console.log(item);//["BIDUPSID", "04B95FD81DCE5E4D68904041B9D32D3B"] ...//这里prev是初始值{}//键名=键值prev[item[0]] = item[1];return prev;}, {});console.log(cookieObj);
Array.prototype.reduceRight()
重写
/*** 重写reduceRight()* 跟reduce,差不多,就是顺序为降序* 归纳函数,对数据进行筛选,归纳* 默认改变不了this的指向,但自己写的话新增改变this指向(参数3)** 基本形态:* [].reduceRight(function(elem,index,arr){});** 改造形态:* [].reduceRight(function(prev,elem,index,arr){},initialValue);** 进行数据过滤* @返回值 不return 为 undefined* @返回值 返回操作后(归纳,筛选)得到的数组** @参数1: 回调函数* @参数2: initialValue(必填)* @回调函数参数1: 操作后返回的数组(第一次默认为[],如有initialValue,用initialValue)* @回调函数参数2: 元素* @回调函数参数3: 索引(可选)* @回调函数参数4: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装myReduceRightArray.prototype.myReduceRight = function (fn, initialValue) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arguments[2], 没传指向windowarg2 = arguments[2] || window;for (var i = len - 1; i >= 0; i--) {item = deepClone(arr[i]);//每遍历一次数组,执行一次回调函数fn//每一次调用fn的返回值就是initialValueinitialValue = fn.apply(arg2, [initialValue, arr[i], i, arr]);//因为第三参数需要改变this指向所以改写为fn.apply(this,[initialValue,参数2,参数3,参数4])}//这里记得return initialValue 否则程序无法正常执行且报错return initialValue;}
Array.prototype.map()
创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
const array1 = [1, 4, 9, 16];// pass a function to mapconst map1 = array1.map((x) => x * 2);console.log(map1);// expected output: Array [2, 8, 18, 32]
语法
var new_array = arr.map(function callback(currentValue, index, array) {// Return element for new_array}, thisArg);
参数
callback:生成新数组元素的函数currentValue:数组中正在处理的当前元素index:可选,当前元素的索引array:可选,当前的数组
thisArg:执行callback函数时值被用作this。
返回值
一个由原数组每个元素执行回调函数的结果组成的新数组。
描述
map方法会给原数组中的每个元素都按顺序调用一次callback函数callback每次执行后的返回值(包括undefined)组合起来形成一个新数组。callback函数只会在有值的索引上被调用;那些从来没被赋过值或者使用delete删除的索引则不会被调用。- 如果
thisArg参数提供给map,则会被用作回调函数的this值。否则undefined会被用作回调函数的this值 map不修改调用它的原数组本身map方法处理数组元素的范围是在callback方法第一次调用之前就已经确定了。调用map方法之后追加的数组元素不会被callback访问。- 如果存在的数组元素改变了,那么传给
callback的值是map访问该元素时的值。在map函数调用后但在访问该元素前,该元素被删除的话,则无法被访问到。
示例
求数组中每个元素的平方根
//创建了一个新数组,值为原数组中对应数字的平方根。var numbers = [1, 4, 9];var roots = numbers.map(Math.sqrt);// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]
使用 map 重新格式化数组中的对象
//使用一个包含对象的数组来重新创建一个格式化后的数组。var kvArray = [{key: 1, value: 10},{key: 2, value: 20},{key: 3, value: 30}];var reformattedArray = kvArray.map(function(obj) {var rObj = {};rObj[obj.key] = obj.value;return rObj;});// reformattedArray 数组为: [{1: 10}, {2: 20}, {3: 30}],// kvArray 数组未被修改:// [{key: 1, value: 10},// {key: 2, value: 20},// {key: 3, value: 30}]
使用一个包含一个参数的函数来mapping(构建)一个数字数组
//当函数需要一个参数时map的工作方式。//当map循环遍历原始数组时,这个参数会自动被分配成数组中对应的每个元素。var numbers = [1, 4, 9];var doubles = numbers.map(function(num) {return num * 2;});// doubles数组的值为: [2, 8, 18]// numbers数组未被修改: [1, 4, 9]
一般的map 方法
//在一个 String 上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组var map = Array.prototype.mapvar a = map.call("Hello World", function(x) {return x.charCodeAt(0);})// a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
querySelectorAll应用
//如何去遍历用 querySelectorAll 得到的动态对象集合。在这里获得了文档里所有选中的选项,并将其打印:var elems = document.querySelectorAll('select option:checked');var values = Array.prototype.map.call(elems, function(obj) {return obj.value;});
重写
//map映射/*** 重写map()** @返回值 返回一个新的数组* @返回值 可以返回参数为元素的元素本身(可不设定条件)* @返回值 可以返回任意加工过的元素数组集合,会改变原数组** @参数1: 回调函数* @参数2: 可更改this指向,默认为window(可选)* @回调函数参数1: 元素* @回调函数参数2: 索引(可选)* @回调函数参数3: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装myMapArray.prototype.myMap = function (fn) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arg2, 没传指向windowarg2 = arguments[1] || window,//新数组容器_newArr = [],item;for (var i = 0; i < len; i++) {//克隆对象item = deepClone(arr[i]);_newArr.push(fn.apply(arg2, [item, i, arr]));}return _newArr;};//参数1:回调函数fn//该函数直接返回修改过元素集合的数组var fn = function (elem, index, array) {//这里编辑返回加工后的结果//会改变原有数据elem.course = this.name + elem.course;//return undefined/null 不会修改数组元素return elem;};//使用myMapvar newArr = courseData.myMap(fn, {name: "test:",});console.log(newArr);
Array.prototype.filter()
创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];const result = words.filter(word => word.length > 6);console.log(result);// expected output: Array ["exuberant", "destruction", "present"]
语法
var newArray = arr.filter(callback(element, index, array), thisArg);
参数
callback:用来测试数组的每个元素的函数。返回true表示该元素通过测试,保留该元素,false则不保element:数组中当前正在处理的元素。index:正在处理的元素在数组中的索引。array:被遍历的数组本身
thisArg:执行callback时,用于this的值。
返回值
一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
描述
filter 不会改变原数组,它返回过滤后的新数组。
filter 遍历的元素范围在第一次调用 callback 之前就已经确定了。
在调用 filter 之后被添加到数组中的元素不会被 filter 遍历到。
如果已经存在的元素被改变了,则他们传入 callback 的值是 filter 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。
示例
筛选排除所有较小的值
创建了一个新数组,该数组的元素由原数组中值大于 10 的元素组成。
function isBigEnough(element) {return element >= 10;}var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);// filtered is [12, 130, 44]
过滤 JSON 中的无效条目
以下示例使用 filter() 创建具有非零 id 的元素的 json。
//filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或等价于 true 的值的元素创建一个新数组。var arr = [{ id: 15 },{ id: -1 },{ id: 0 },{ id: 3 },{ id: 12.2 },{ },{ id: null },{ id: NaN },{ id: 'undefined' }];var invalidEntries = 0;function isNumber(obj) {return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj);}function filterByID(item) {if (isNumber(item.id) && item.id !== 0) {return true;}invalidEntries++;return false;}var arrByID = arr.filter(filterByID);console.log('Filtered Array\n', arrByID);// Filtered Array// [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]console.log('Number of Invalid Entries = ', invalidEntries);// Number of Invalid Entries = 5
在数组中搜索
下例使用 filter() 根据搜索条件来过滤数组内容。
var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];function filterItems(query) {return fruits.filter(function(el) {return el.toLowerCase().indexOf(query.toLowerCase()) > -1;})}/*** console.log('apple'.indexOf('ap')); //0* console.log('apple'.indexOf('an')); //-1* console.log('banana'.indexOf('an')); //1* console.log('orange'.indexOf('an')); //2*/console.log(filterItems('ap')); // ['apple', 'grapes']console.log(filterItems('an')); // ['banana', 'mango', 'orange']
重写
/*** 重写filter()* 进行数据过滤* @返回值 true返回一个新的数组(不影响原来的数组)* @返回值 false返回一个空的数组* @返回值 条件符合 -> true -> 返回符合条件内容** @参数1: 回调函数* @参数2: 可更改this指向,默认为window(可选)* @回调函数参数1: 元素* @回调函数参数2: 索引(可选)* @回调函数参数3: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装myFilterArray.prototype.myFilter = function (fn) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arg2, 没传指向windowarg2 = arguments[1] || window,//新数组容器_newArr = [],item;for (var i = 0; i < len; i++) {//每遍历一次数组,执行一次回调函数fn// fn(arr[i], i, arr);//因为第二参数需要改变this指向所以改写为fn.apply(参数1,[参数1,参数2])//为真: push到新数组//为假: 不做任何操作//注意: push(arr[i])里面还是持有原来数据的引用,修改会影响原有数据//解决方法: 需要深拷贝item = deepClone(arr[i]);fn.apply(arg2, [arr[i], i, arr]) ? _newArr.push(item) : '';}return _newArr;}//使用myFiltervar newArr = courseData.myFilter(function (elem, index, array) {//这里返回true且符合条件的数据 / falsereturn elem.is_free === '0';}, {name: 'test'})console.log(newArr);
备注:这里是深拷贝的封装代码
//循环对象之前需要检测对象里面的属性值是否是引用值//当发现有引用值的时候需要遍历//不仅判断键值对是否含有引用值,还得判断是对象还是数组//利用递归克隆函数进行再次循环function deepClone(origin, target) {//万一用户不传target参数,自己默认创建空对象var target = target || {},toStr = Object.prototype.toString,arrType = '[object Array]';for (var key in origin) {//排除原型上的属性if (origin.hasOwnProperty(key)) {//判断是否为引用值 同时排除nullif (typeof (origin[key]) === 'object' && origin[key] !== null) {//判断引用值是否为数组类型if (toStr.call(origin[key]) === arrType) {//创建空数组target[key] = [];} else {//引用值是对象//创建空对象target[key] = {};}//递归,再次遍历deepClone(origin[key], target[key]);} else {//这里是递归的出口//遍历第一层 浅拷贝target[key] = origin[key];}}}return target;}
Array.prototype.forEach()
对数组的每个元素执行一次给定的函数。总是返回 undefined 值,并且不可链式调用。
注意: 除了抛出异常以外,没有办法中止或跳出
forEach()循环。
const array1 = ['a', 'b', 'c'];array1.forEach(element => console.log(element));// expected output: "a"// expected output: "b"// expected output: "c"
语法
arr.forEach(callback(currentValue, index, array), thisArg)
参数
callback:为数组中每个元素执行的函数currentValue:数组中正在处理的当前元素index:可选,数组中正在处理的当前元素索引array:可选,正在操作的数组
thisArg:可选,当执行回调函数callback时,用作this的值
返回值
undefined
示例
不对未初始化的值进行任何操作(稀疏数组)
const arraySparse = [1, 3, , 7];let numCallbackRuns = 0;arraySparse.forEach(function (element) {console.log(element);numCallbackRuns++;});console.log("numCallbackRuns: ", numCallbackRuns);// 1// 3// 7// numCallbackRuns: 3
将 for 循环转换为 forEach
const items = ['item1', 'item2', 'item3'];const copy = [];// beforefor (let i = 0; i < items.length; i++) {copy.push(items[i]);}// afteritems.forEach(function (item) {copy.push(item);});
//打印出数组的内容function logArrayElements(element, index, array) {console.log(`a[${index}]=` + element);}// 注意索引 2 被跳过了,因为在数组的这个位置没有项[2, 5, , 9].forEach(logArrayElements);// logs:// a[0] = 2// a[1] = 5// a[3] = 9
素材:data数据
var courseData = [{"id": "1","course": "前端开发之企业级深度JavaScript特训课【JS++前端】","classes": "19","teacher": "小野","img": "ecmascript.jpg","is_free": "1","datetime": "1540454477","price": "0"},{"id": "2","course": "WEB前端工程师就业班之深度JS DOM+讲师辅导-第3期【JS++前端】","classes": "22","teacher": "小野","img": "dom.jpg","is_free": "0","datetime": "1540454477","price": "699"},{"id": "3","course": "前端开发之企业级深度HTML特训课【JS++前端】","classes": "3","teacher": "小野","img": "html.jpg","is_free": "1","datetime": "1540454477","price": "0"},{"id": "4","course": "前端开发之企业级深度CSS特训课【JS++前端】","classes": "5","teacher": "小野","img": "css.jpg","is_free": "1","datetime": "1540454477","price": "0"},{"id": "5","course": "前端就业班VueJS+去哪儿网+源码课+讲师辅导-第3期【JS++前端】","classes": "50","teacher": "哈默","img": "vuejs.jpg","is_free": "0","datetime": "1540454477","price": "1280"},{"id": "6","course": "前端就业班ReactJS+新闻头条实战+讲师辅导-第3期【JS++前端】","classes": "21","teacher": "托尼","img": "reactjs.jpg","is_free": "0","datetime": "1540454477","price": "2180"},{"id": "7","course": "WEB前端开发工程师就业班-直播/录播+就业辅导-第3期【JS++前端】","classes": "700","teacher": "JS++名师团","img": "jiuyeban.jpg","is_free": "0","datetime": "1540454477","price": "4980"}]
重写
/*** 重写forEach()* @参数1: 回调函数* @参数2: 可更改this指向,默认为window(可选)* @回调函数参数1: 元素* @回调函数参数2: 索引(可选)* @回调函数参数3: 数组本身(可选)** 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*/Array.prototype.myForEach = function (fn) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arg2, 没传指向windowarg2 = arguments[1] || window;for (var i = 0; i < len; i++) {//每遍历一次数组,执行一次回调函数fn// fn(arr[i], i, arr);//因为第二参数需要改变this指向所以改写为fn.apply(参数1,[参数1,参数2])fn.apply(arg2, [arr[i], i, arr]);}}//使用myForEachcourseData.myForEach(function (elem, index, array) {console.log(elem.course);})
Array.prototype.every()
测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
注意:若收到一个空数组,此方法在一切情况下都会返回
true。
const isBelowThreshold = (currentValue) => currentValue < 40;const array1 = [1, 30, 39, 29, 10, 13];console.log(array1.every(isBelowThreshold));// expected output: true
语法
arr.every(callback(element, index, array), thisArg);
参数
callback:用来测试每个元素的函数element:用来测试的当前值index:可选,用来测试的当前值的索引array:可选,当前数组
thisArg:执行callback时使用的this值。
返回值
如果回调函数的每一次返回都为 truthy 值,返回 true ,否则返回 false。
描述
every方法为数组中的每个元素执行一次callback函数,直到它找到一个会使callback返回 falsy 的元素。- 如果发现了一个这样的元素,
every方法将会立即返回false。否则,callback为每一个元素返回true,every就会返回true。 callback只会为那些已经被赋值的索引调用。不会为那些被删除或从未被赋值的索引调用。- 如果为
every提供一个thisArg参数,则该参数为调用callback时的this值。如果省略该参数,则callback被调用时的this值,在非严格模式下为全局对象,在严格模式下传入undefined。 every不会改变原数组。every和数学中的”所有”类似,当所有的元素都符合条件才会返回true。正因如此,若传入一个空数组,无论如何都会返回true。
示例
检测所有数组元素的大小
//检测数组中的所有元素是否都大于 10。function isBigEnough(element, index, array) {return element >= 10;}[12, 5, 8, 130, 44].every(isBigEnough); // false[12, 54, 18, 130, 44].every(isBigEnough); // true//箭头函数形式[12, 5, 8, 130, 44].every(x => x >= 10); // false[12, 54, 18, 130, 44].every(x => x >= 10); // true
分析every
//分析everyvar res = courseData.every(function (elem, index, array) {//elem.is_free == "0" -> 收费课//情况1:只打印一条数据且因不满足返回false//这里是第一条不满足条件的数据(免费课)console.log(elem);return elem.is_free == "0";//情况2:打印所有数据且因满足返回trueconsole.log(elem);return elem.is_free;});console.log(res); // false/true
重写
/*** 重写every()* 特点:* 1. 如果有一个不满足条件就停止遍历,条件就是return后面表达式* 2. 返回布尔值** @返回值 返回满足条件为true* @返回值 返回不满足条件为false** @参数1: 回调函数* @参数2: 可更改this指向,默认为window(可选)* @回调函数参数1: 元素* @回调函数参数2: 索引(可选)* @回调函数参数3: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装myEveryArray.prototype.myEvery = function (fn) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arg2, 没传指向windowarg2 = arguments[1] || window,//初始化返回值结果res = true;for (var i = 0; i < len; i++) {//判断回调函数的返回值是真或假if (!fn.apply(arg2, [arr[i], i, arr])) {res = false;break;}}return res;};//参数1:回调函数fnvar fn = function (elem, index, array) {return elem.is_free == "0";};//使用myEveryvar result = courseData.myEvery(fn, {name: "test:",});console.log(result); //false
Array.prototype.some()
测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
注意:如果用一个空数组进行测试,在任何情况下它返回的都是
false。
const array = [1, 2, 3, 4, 5];// checks whether an element is evenconst even = (element) => element % 2 === 0;console.log(array.some(even));// expected output: true
语法
arr.some(callback(element, index, array), thisArg);
参数
callback:用来测试每个元素的函数element:数组上正在处理的元素index:可选,数组中正在处理的元素的索引值array:可选,当前数组
thisArg:可选,执行callback时使用的this值。
返回值
数组中有至少一个元素通过回调函数的测试就会返回true;所有元素都没有通过回调函数的测试返回值才会为false。
描述
some()为数组中的每一个元素执行一次callback函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。- 如果找到了这样一个值,
some()将会立即返回true。否则,some()返回false。 callback只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。
示例
测试数组元素的值
//检测在数组中是否有元素大于 10。function isBiggerThan10(element, index, array) {return element > 10;}[2, 5, 8, 1, 4].some(isBiggerThan10); // false[12, 5, 8, 1, 4].some(isBiggerThan10); // true//箭头函数形式[2, 5, 8, 1, 4].some(x => x > 10); // false[12, 5, 8, 1, 4].some(x => x > 10); // true
判断数组元素中是否存在某个值
//模仿 includes() 方法, 若元素在数组中存在, 则回调函数返回值为 truevar fruits = ['apple', 'banana', 'mango', 'guava'];function checkAvailability(arr, val) {return arr.some(function(arrVal) {return val === arrVal;});}checkAvailability(fruits, 'kela'); // falsecheckAvailability(fruits, 'banana'); // true//箭头函数形式var fruits = ['apple', 'banana', 'mango', 'guava'];function checkAvailability(arr, val) {return arr.some(arrVal => val === arrVal);}checkAvailability(fruits, 'kela'); // falsecheckAvailability(fruits, 'banana'); // true
将任意值转换为布尔类型
var TRUTHY_VALUES = [true, 'true', 1];function getBoolean(value) {'use strict';if (typeof value === 'string') {value = value.toLowerCase().trim();}return TRUTHY_VALUES.some(function(t) {return t === value;});}getBoolean(false); // falsegetBoolean('false'); // falsegetBoolean(1); // truegetBoolean('true'); // true
重写
/*** 重写some()* 特点:* 1. 如果有一个满足条件就停止遍历,条件就是return后面表达式* 2. 返回布尔值** @返回值 返回任一满足条件为true* @返回值 返回所有不满足条件为false** @参数1: 回调函数* @参数2: 可更改this指向,默认为window(可选)* @回调函数参数1: 元素* @回调函数参数2: 索引(可选)* @回调函数参数3: 数组本身(可选)** 要求:* 1.必须数组调用* 2.第二参数必须为强制进行对象包装不包括undefined和null, 因为this必须指向对象* 3.兼容IE和es3*///封装mySomeArray.prototype.mySome = function (fn) {var arr = this,//兼容es3只能for循环len = arr.length,//第二参数可传可不传利用arguments[1]//传了指向arg2, 没传指向windowarg2 = arguments[1] || window,//初始化返回值结果res = false;for (var i = 0; i < len; i++) {//判断回调函数的返回值是真或假if (fn.apply(arg2, [arr[i], i, arr])) {res = true;break;}}return res;};//参数1:回调函数fnvar fn = function (elem, index, array) {return elem.is_free == "0";};//使用mySomevar result = courseData.mySome(fn, {name: "test:",});console.log(result); //true
Array.prototype.slice.call(arguments)
能将有length属性的对象转换为数组
类似ES6的Array.of()方法
function list() {return Array.prototype.slice.call(arguments);}console.log(list('123'));//["123"]console.log(list(1));//[1]console.log(list(1, 2, 3));//[1, 2, 3]console.log(list(true));//[true]console.log(list(undefined));//[undefined]console.log(list(null));//[null]console.log(list(NaN));//[NaN]console.log(list(0));//[0]console.log(list(false));//[false]console.log(list(function () {}));//[ƒ]console.log(list(new String('abc')));//[String]console.log(list(new Number(123)));//[Number]console.log(list(new Boolean(true)));//[Boolean]
Array.of()
ECMAScript 2015 ES6
创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
console.log(Array.of(7)); // [7]console.log(Array.of(1, 2, 3)); //[1, 2, 3]console.log(Array(7)); //[empty × 7]console.log(Array(1, 2, 3));; // [1, 2, 3]
语法
Array.of(element0[, element1[, ...[, elementN]]])
参数
elementN:任意个参数,将按顺序成为返回数组中的元素。
返回值
新的 Array 实例。
参数/返回值:
console.log(Array.of('123'));; //["123"]console.log(Array.of(1)); // [1]console.log(Array.of(1, 2, 3)); // [1, 2, 3]console.log(Array.of(true)); //[true]console.log(Array.of(undefined)); //[undefined]console.log(Array.of(null)); //[null]console.log(Array.of(NaN)); //[NaN]console.log(Array.of(0)); //[0]console.log(Array.of(false)); //[false]console.log(Array.of({})); //[{…}]console.log(Array.of([])); //[Array(0)]console.log(Array.of(function () {})); //[ƒ]console.log(Array.of(new String('abc'))); //[String] 0: String {"abc" length: 1 __proto__: Array(0)console.log(Array.of(new Number(123))); //[Number] 0: Number {123} length: 1 __proto__: Array(0)console.log(Array.of(new Boolean(true))); //[Boolean] 0: Boolean {true} length: 1 __proto__: Array(0)
兼容写法:
if (!Array.of) {Array.of = function() {return Array.prototype.slice.call(arguments);};}
function list() {return Array.prototype.slice.call(arguments);}console.log(list('123'));//["123"]console.log(list(1));//[1]console.log(list(1, 2, 3));//[1, 2, 3]console.log(list(true));//[true]console.log(list(undefined));//[undefined]console.log(list(null));//[null]console.log(list(NaN));//[NaN]console.log(list(0));//[0]console.log(list(false));//[false]console.log(list(function () {}));//[ƒ]console.log(list(new String('abc')));//[String]console.log(list(new Number(123)));//[Number]console.log(list(new Boolean(true)));//[Boolean]
Array.from()
ECMAScript 2015 ES6
从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
console.log(Array.from('foo'));//["f", "o", "o"]console.log(Array.from([1, 2, 3], x => x + x));//[2, 4, 6]
语法
Array.from(arrayLike, mapFn, thisArg);
参数
arrayLike:想要转换成数组的伪数组对象或可迭代对象。mapFn:如果指定了该参数,新数组中的每个元素会执行该回调函数。thisArg:可选参数,执行回调函数mapFn时this对象。
返回值
一个新的数组实例。
Array.from() 可以通过以下方式来创建数组对象:
- 伪数组对象(拥有一个
length属性和若干索引属性的任意对象) - 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)
//参数是一个数组//返回一个新的数组引用const arr = [1, 2, 3];const newArr = Array.from(arr);console.log(newArr); //[1, 2, 3]console.log(arr === newArr); //false
//参数是一个带有引用类型元素的数组//返回的新数组是一个浅拷贝const arr = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'},{id: 3,name: 'wangwu'}]const newArr = Array.from(arr);console.log(newArr);console.log(arr[1] === newArr[1]); //true/*** (3) [{…}, {…}, {…}]* 0: {id: 1, name: "zhangsan"}* 1: {id: 2, name: "lisi"}* 2: {id: 3, name: "wangwu"}* length: 3* __proto__: Array(0)*/
//参数是一个字符串//字符串底层new String出来也具有可迭代对象const str = '123';const newArr = Array.from(str);console.log(newArr);//["1", "2", "3"]console.log(new String('123'));/*** String {"123"}* 0: "1"* 1: "2"* 2: "3"* length: 3* __proto__: String* Symbol(Symbol.iterator): ƒ [Symbol.iterator]()*/
参数1/返回值:
- 参数为空,报错
- 参数如果是一个
undefined或null,报错 - 参数如果为空,报错
- 参数如果是一个Symbol,不做处理返回一个空数组
- 参数如果是一个数字,不做处理返回一个空数组
- 参数如果是一个布尔值,不做处理返回一个空数组
- 参数如果是一个正则,不做处理返回一个空数组
- 参数如果是一个普通对象,不做处理返回一个空数组
- 参数如果是一个数组,不做处理返回一个空数组
console.log(Array.from());//Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))console.log(Array.from(Symbol('123')));//[]console.log(Array.from(123));//[]console.log(Array.from('123'));//["1", "2", "3"]console.log(Array.from(true));//[]console.log(Array.from(false));//[]console.log(Array.from(/123/));//[]console.log(Array.from(undefined));//Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))console.log(Array.from(null));//Uncaught TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))console.log(Array.from(NaN));//[]console.log(Array.from(0));//[]console.log(Array.from({}));//[]console.log(Array.from([]));//[]console.log(Array.from(new String('abc')));//["a", "b", "c"]console.log(Array.from(new Number(456)));//[]console.log(Array.from(new Boolean(true)));//[]
//参数为类数组 依赖lengthconst arrLike = {0: 1,1: 2,2: 3,length: 3}console.log(Array.from(arrLike));//[1, 2, 3]//键名一定要按照数组对应下标的数字const arrLike2 = {a: 1,b: 2,c: 3,length: 3}console.log(Array.from(arrLike2));//[undefined, undefined, undefined]
类数组正常返回一个对应的数组的必要条件:
- 键名必须冲0开始按数字顺序排列
- length属性必须正确
- 长度决定了新数组的长度,属性名决定了填充该数组的位置
从 Map 生成数组:
//参数是一个Mapconst m = new Map([['a', 1],['b', 2],['c', 3]]);console.log(m);/*** Map(3) {"a" => 1, "b" => 2, "c" => 3}* [[Entries]]* 0: {"a" => 1}* key: "a"* value: 1* 1: {"b" => 2}* 2: {"c" => 3}* size: (...)* __proto__: Map*/console.log(Array.from(m));/*** (3) [Array(2), Array(2), Array(2)]* 0: (2) ["a", 1]* 1: (2) ["b", 2]* 2: (2) ["c", 3]* length: 3* __proto__: Array(0)*/
从 Set 生成数组:
//参数是一个Setconst s = new Set([1, 2, 3, 4]);console.log(s);/*** Set(4) {1, 2, 3, 4}* [[Entries]]* 0: 1* 1: 2* 2: 3* 3: 4* size: (...)* __proto__: Set*/console.log(Array.from(s));//[1, 2, 3, 4]
参数2/参数3/返回值:
从类数组对象(arguments)生成数组:
/*** Array.from()* @arguments[0] 必填 第一个参数必须要是可迭代对象或者标准的类数组* @arguments[1] 第二个参数为回调函数* @arguments[2] 第三个参数为可以更改回调内this指向* @item 当前遍历的元素* @index 当前遍历的元素在数组中对应的下标* @this 默认指向window 严格模式为undefined*/const arrLike = {0: 1,1: 2,2: 3,length: 3}const newArr = Array.from(arrLike, function (item, index, arr) {//每一次遍历必须返回一个值//由于回调执行的时候,Array.from还没有执行完毕,所以不存在逻辑上的新数组//所以无法在回调里获取到新数组本身(有别于数组的其他遍历方法)console.log(item); //1 2 3console.log(index); //0 1 2console.log(arr); //undefinedconsole.log(this); //windowreturn item + 1;}, {a: 1})console.log(newArr); //[2, 3, 4]
//论Array.from()第二参数的执行原理const newArr = Array.from(arrLike).map(function (item, index, arr) {console.log(item, index, arr); //可打印return item + 1;});console.log(newArr); //[2, 3, 4]
//证明from方法的第一个参数是必填项console.log(Array.from.length); //1
序列生成器(指定范围):
//填充数组 - 序列生成器//range(start, end, 间隔)//[1, 3, 5, 7, 9];const r = range(1, 10, 2);function range(start, stop, step) {return Array.from({length: (stop - start) / step + 1}, function (item, index) {//1 + (0 * 2) = 1//1 + (1 * 2) = 3//1 + (2 * 2) = 5return start + (index * step);})}console.log(r);//[1, 3, 5, 7, 9]
数组去重合并:
//数组的合并于去重function combine() {const arr = Array.prototype.concat.apply([], arguments);//Set集合结构本来有唯一性的特点return Array.from(new Set(arr));}const arr1 = [1, 2, 3, 4, 5];const arr2 = [2, 3, 4, 5, 6];const arr3 = [3, 4, 5, 6, 7];console.log(combine(arr1, arr2, arr3));//[1, 2, 3, 4, 5, 6, 7]
//Array.from的源码实现//参数1:可迭代对象或者类数组 必填//参数2:mapFn 可选//参数3:this指向 可选Array.myFrom = (function () {//可不可以调用的函数const isCallable = function (fn) {return typeof fn === 'function' || Object.prototype.toString.call(fn) === '[object Function]';}//转换length 返回成正整数或者负整数const toInt = function (value) {const v = Number(value);//有可能转换出来的数字为非数字if (isNaN(v)) {return 0;}//!isFinite()不是无穷大的数if (v === 0 || !isFinite(v)) {return v;}//先取绝对值后向下取整return (v > 0 ? 1 : -1) * Math.floor(Math.abs(v));}//最大length的范围//常识:2的53次幂为JS最大的安全正整数const maxSafeInt = Math.pow(2, 53) - 1;const toLength = function (value) {const len = toInt(value);return Math.min(Math.max(len, 0), maxSafeInt);}return function (arrayLike) {//保持调用方//Array.myFromconst caller = this;if (arrayLike === null) {throw new TypeError('Method from requires an array-like object');}//包装arrayLike对象const origin = Object(arrayLike);//改变this指向的参数let arg2;//有传第二个参数 or 生成 undefinedconst mapFn = arguments.length > 1 ? arguments[1] : void undefined;if (typeof mapFn !== 'undefined') {//不可调用if (!isCallable(mapFn)) {throw new TypeError('mapFn must be a function');}//传递第三个参数if (arguments.length > 2) {arg2 = arguments[2];}}const len = toLength(origin.length);const arr = isCallable(caller) ? Object(new caller(len)) : new Array(len);let i = 0,val;while (i < len) {val = origin[i];if (mapFn) {arr[i] = typeof arg2 === 'undefined' ? mapFn(val, i) : mapFn.apply(arg2, [val, i]);} else {arr[i] = val;}i++;}return arr;}})();const arrLike = {0: 1,1: 2,2: 3,length: 3}const newArr = Array.myFrom(arrLike);console.log(newArr); //[1, 2, 3]const newArr2 = Array.myFrom(arrLike, function (item, index) {console.log(item);console.log(index);return item + 1;});console.log(newArr2); //[2, 3, 4]
字符串方法
String.prototype.split()
使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。
返回值
- 返回源字符串以分隔符出现位置分隔而成的一个 Array
参数
separator:指定表示每个拆分应发生的点的字符串。
//join();//默认逗号隔开元素//跟toString()一样var arr = ['a', 'b', 'c', 'd'];var str1 = arr.join();var str2 = arr.toString();console.log(str1); //a,b,c,dconsole.log(str2); //a,b,c,d//参数//指定隔开符号console.log(arr.join('')); //abcdconsole.log(arr.join('-')); //a-b-c-dconsole.log(arr.join('&')); //a&b&c&dconsole.log(arr.join(0)); //a0b0c0d
//split();//split()默认不传参可以把字符串转为数组//join('-') 和 split('-') 保持分隔符一致才能分开数字元素var arr = ['a', 'b', 'c', 'd'];var str1 = arr.join('-');var arr1 = str1.split();console.log(str1); //a-b-c-dconsole.log(arr1); //["a-b-c-d"]console.log('--------------------------------------');//参数1//参数传入'-'可以分割数组元素//参数传入',' 不可以分割数组元素//参数传入'' 分割数组元素var str2 = arr.join('-');var arr2 = str2.split('-');var arr3 = str2.split(',');var arr4 = str2.split('');console.log(str2); //a-b-c-dconsole.log(arr2); //["a", "b", "c", "d"]console.log(arr3); //["a-b-c-d"]console.log(arr4); //["a", "-", "b", "-", "c", "-", "d"]console.log('--------------------------------------');//参数2//传入数字 截断下标号之前(不包括)var str3 = arr.join('-');var arr5 = str3.split('-', 4);var arr6 = str3.split('-', 3);var arr7 = str3.split('-', 2);var arr8 = str3.split('-', 1);console.log(str3); //a-b-c-dconsole.log(arr5); //["a", "b", "c", "d"]console.log(arr6); //["a", "b", "c"]console.log(arr7); //["a", "b"]console.log(arr8); //["a"]
const str = 'The quick brown fox jumps over the lazy dog.';const words = str.split(' ');console.log(words);//["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."]console.log(words[3]);// expected output: "fox"const chars = str.split('');console.log(chars);//["T", "h", "e", " ", "q", "u", "i", "c", "k", " ", "b", "r", "o", "w", "n", " ", "f", "o", "x", " ", "j", "u", "m", "p", "s", " ", "o", "v", "e", "r", " ", "t", "h", "e", " ", "l", "a", "z", "y", " ", "d", "o", "g", "."]console.log(chars[8]);// expected output: "k"const strCopy = str.split();console.log(strCopy);//["The quick brown fox jumps over the lazy dog."]console.log(strCopy[0]);// expected output: Array ["The quick brown fox jumps over the lazy dog."]
传参/返回值:
- 传入
[],返回包含逗号的所有数组元素 - 传入跟
join()一样的参数时会返回逗号分割的数组元素 - 若
join()传入参数且split()没有传参会返回字符串转数组的结果
var arr = ['a', 'b', 'c'];console.log(arr, arr.join(), arr.join().split('e'));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(5));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(true));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(undefined));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(null));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(NaN));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(0));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(false));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split({}));//["a", "b", "c"] "a,b,c" ["a,b,c"]//连逗号也分割console.log(arr, arr.join(), arr.join().split([]));//["a", "b", "c"] "a,b,c" (5) ["a", ",", "b", ",", "c"]console.log(arr, arr.join(), arr.join().split(function () {}));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(new String('123')));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(new Number(123)));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split(new Boolean(true)));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join(), arr.join().split('&'));//["a", "b", "c"] "a,b,c" ["a,b,c"]console.log(arr, arr.join('&'), arr.join('&').split('&'));//["a", "b", "c"] "a&b&c" (3) ["a", "b", "c"]console.log(arr, arr.join('&'), arr.join('&').split());//["a", "b", "c"] "a&b&c" ["a&b&c"]console.log(arr, arr.join('-'), arr.join('-').split('-'));//["a", "b", "c"] "a-b-c" (3) ["a", "b", "c"]console.log(arr, arr.join('-'), arr.join('-').split());//["a", "b", "c"] "a-b-c" ["a-b-c"]console.log(arr, arr.join(''), arr.join('').split(''));//["a", "b", "c"] "abc" (3) ["a", "b", "c"]console.log(arr, arr.join(''), arr.join('').split());//["a", "b", "c"] "abc" ["abc"]console.log(arr, arr.join(' '), arr.join(' ').split(' '));//["a", "b", "c"] "a b c" (3) ["a", "b", "c"]console.log(arr, arr.join(' '), arr.join(' ').split());//["a", "b", "c"] "a b c" ["a b c"]
String.prototype.valueOf()
返回 String 对象的原始值
const stringObj = new String('foo');console.log(stringObj);// expected output: String { "foo" }console.log(stringObj.valueOf());// expected output: "foo"
语法
str.valueOf()
返回值
返回 String 对象的原始值
参数/返回值:
console.log(new String('Hello world'), new String('Hello world').valueOf());//String {"Hello world"} "Hello world"console.log(new String('123456'), new String('123456').valueOf());//String {"123456"} "123456"console.log(new String(123456), new String(123456).valueOf());//String {"123456"} "123456"console.log(new Number(123456), new Number(123456).valueOf());//Number {123456} 123456console.log(new String(true), new String(true).valueOf());//String {"true"} 0: "t"1: "r"2: "u"3: "e" length: 4__proto__: String[[PrimitiveValue]]: "true" "true"console.log(new String(false), new String(false).valueOf());//String {"false"} 0: "f"1: "a"2: "l"3: "s"4: "e" length: 5__proto__: String[[PrimitiveValue]]: "false" "false"console.log(new String(undefined), new String(undefined).valueOf());//String {"undefined"} "undefined"console.log(new String(NaN), new String(NaN).valueOf());//String {"NaN"} 0: "N"1: "a"2: "N" length: 3__proto__: String[[PrimitiveValue]]: "NaN" "NaN"console.log(new String(null), new String(null).valueOf());//String {"null"} "null"console.log(new String(0), new String(0).valueOf());//String {"0"} "0"console.log(new String({}), new String({}).valueOf());//String {"[object Object]"}0: "["1: "o"2: "b"3: "j"4: "e"5: "c"6: "t"7: " "8: "O"9: "b"10: "j"11: "e"12: "c"13: "t"14: "]"length: 15 __proto__: String[[PrimitiveValue]]: "[object Object]" "[object Object]"console.log(new String([]), new String([]).valueOf());//String {""} length: 0 __proto__: String[[PrimitiveValue]]: ""console.log(new String(function () {}), new String(function () {}).valueOf());//String {"function () {}"} 0: "f"1: "u"2: "n"3: "c"4: "t"5: "i"6: "o"7: "n"8: " "9: "("10: ")"11: " "12: "{"13: "}" length: 14__proto__: String[[PrimitiveValue]]: "function () {}" "function () {}"
String.prototype.slice()
提取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。
const str = 'The quick brown fox jumps over the lazy dog.';console.log(str.slice(31));// expected output: "the lazy dog."console.log(str.slice(4, 19));// expected output: "quick brown fox"console.log(str.slice(-4));// expected output: "dog."console.log(str.slice(-9, -5));// expected output: "lazy"
语法
str.slice(beginIndex, endIndex);
参数
beginIndex:从该索引(以 0 为基数)处开始提取原字符串中的字符。- 如果值为负数,会被当做
strLength + beginIndex看待
- 如果值为负数,会被当做
endIndex:可选。在该索引(以 0 为基数)处结束提取字符串。- 如果省略该参数,
slice()会一直提取到字符串末尾。 - 如果该参数为负数,则被看作是 strLength + endIndex 看待
- 如果省略该参数,
返回值
返回一个从原字符串中提取出来的新字符串
使用 slice() 创建了一个新字符串。
var str1 = 'The morning is upon us.', // str1 的长度 length 是 23。str2 = str1.slice(1, 8),str3 = str1.slice(4, -2),str4 = str1.slice(12),str5 = str1.slice(30);console.log(str2); // 输出:he mornconsole.log(str3); // 输出:morning is upon uconsole.log(str4); // 输出:is upon us.console.log(str5); // 输出:""
使用 slice() 时传入了负值作为索引
var str = 'The morning is upon us.';str.slice(-3); // 返回 'us.'str.slice(-3, -1); // 返回 'us'str.slice(0, -1); // 返回 'The morning is upon us'
String.prototype.substring()
返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。
语法
str.substring(indexStart, indexEnd);
参数
indexStart:需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母。indexEnd:可选。一个 0 到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。
返回值
包含给定字符串的指定部分的新字符串。
描述
substring 提取从 indexStart 到 indexEnd(不包括)之间的字符。特别地:
- 如果
indexStart等于indexEnd,substring返回一个空字符串。 - 如果省略
indexEnd,substring提取字符一直到字符串末尾。 - 如果任一参数小于 0 或为
NaN,则被当作 0。 - 如果任一参数大于
stringName.length,则被当作stringName.length。 - 如果
indexStart大于indexEnd,则substring的执行效果就像两个参数调换了一样。
var anyString = "Mozilla";// 输出 "Moz"console.log(anyString.substring(0,3));console.log(anyString.substring(3,0));console.log(anyString.substring(3,-3));console.log(anyString.substring(3,NaN));console.log(anyString.substring(-2,3));console.log(anyString.substring(NaN,3));// 输出 "lla"console.log(anyString.substring(4,7));console.log(anyString.substring(7,4));// 输出 ""console.log(anyString.substring(4,4));// 输出 "Mozill"console.log(anyString.substring(0,6));// 输出 "Mozilla"console.log(anyString.substring(0,7));console.log(anyString.substring(0,10));
运用 length 属性来使用 substring()
// String.length 属性去获取指定字符串的倒数元素。显然这个办法更容易记住,因为你不再像上面那个例子那样去记住起始位置和最终位置。// Displays 'illa' the last 4 charactersvar anyString = 'Mozilla';var anyString4 = anyString.substring(anyString.length - 4);console.log(anyString4);// Displays 'zilla' the last 5 charactersvar anyString = 'Mozilla';var anyString5 = anyString.substring(anyString.length - 5);console.log(anyString5);
替换一个字符串的子字符串
//替换了一个字符串中的子字符串。可以替换单个字符和子字符串。//该例结尾调用的函数将 "Brave New World" 变成了 "Brave New Web"function replaceString(oldS, newS, fullS) {// Replaces oldS with newS in the string fullSfor (var i = 0; i < fullS.length; i++) {if (fullS.substring(i, i + oldS.length) == oldS) {fullS = fullS.substring(0, i) + newS + fullS.substring(i + oldS.length, fullS.length);}}return fullS;}replaceString("World", "Web", "Brave New World");
//如果 oldS 是 newS 的子字符串将会导致死循环。例如,尝试把 "Web" 替换成 "OtherWorld"。一个更好的方法如下:function replaceString(oldS, newS,fullS){return fullS.split(oldS).join(newS);}
对象方法
Object.is()
判断两个值是否为同一个值。
Object.is() 方法判断两个值是否为同一个值。如果满足以下条件则两个值相等:
- 都是 undefined
- 都是 null
- 都是 true 或 false
- 都是相同长度的字符串且相同字符按相同顺序排列
- 都是相同对象(意味着每个对象有同一个引用)
都是数字且
- 都是 +0
- 都是 -0
- 都是 NaN
- 或都是非零而且非 NaN 且为同一个
与== 运算不同。 == 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 “” == false 判断为 true), 而 Object.is不会强制转换两边的值。
与=== 运算也不相同。 === 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等 ,而将Number.NaN 与NaN视为不相等.
JS中相等性判断
ES6版本,四种相等判断的算法
//全等 三等 ===//等于 ==//零值相等 -0 === +0//同值相等 -0 !== +0 NaN === NaN
//JS中提供有关相等判断的操作方法//严格相等 === Strict Equality//非严格相等(抽象/非约束) 相等 == Loose(自由的,不受限制的) Equality//Object.is(v1, v2); ES6新API, 判断两个参数是否是同一个值// === 严格相等//不进行隐式类型转换 - 类型相同/值也相同// 1 === '1' ? false 1 === 2 ? false//引用值必须是同一个地址//var obj = {} obj === obj ? true {} === {} ? false//两个NaN 或者是 NaN跟其他值都不相等//NaN === NaN ? false NaN === undefined ? false//+0 和 -0 相等//+0 === -0 ? true//+ Infinity 与 - Infinity 相等//+ Infinity === - Infinity ? false//如何定义变量a a !== a -> true -> NaN//非严格相等 Abstract equality//隐式类型转换 - 等式两边都有可能被转换//转换以后还是用严格相等来比较//ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)。//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness#%E9%9D%9E%E4%B8%A5%E6%A0%BC%E7%9B%B8%E7%AD%89//任何对象都与undefined null 不相等//窄对象 Narrow Object -> document.all[]//document.all == undefined//全等对结果的预测是更加清晰明确//全等在不隐式类型转换的前提下更快//1 '1' function//fasly值 8个//false 0 +/-0 8n '' "" `` null undefind NaN//同值相等 same-value//零值相等 same-value-zero +0 === -0//-0 !== +0 -> 同值相等//NaN === NaN -> 同值相等// var obj = {}// Object.defineProperty(obj, 'myZero'. {// value: -0,// writable: false,// configurable: false,// enumerable: false// });// //+0/0 都会抛出 异常,不能重新定义myZero属性// Object.defineProperty(obj, 'myZero', {// value: -0// })// Object.defineProperty(obj, 'myNaN', {// value: NaN,// writable: false,// configurable: false,// enumerable: false// })// Object.defineProperty(obj, 'myNaN', {// value: NaN// })
//同值相等的底层实现 Object.is()//ES6抛出来的方法//ES5并没有暴露JS引擎的同值相等的方法//Object.is()//ES2015 ES6//同值相等的实现// var a = 1;// var b = '1';//false// var a = +0;// var b = -0;//false// var a = NaN;// var b = NaN;//true// var res = Object.is(a, b);// console.log(res); //false// var obj = {};//参数就是两个值,返回值就是通知相等判断的布尔结果// const res = Object.is(undefined, undefined);//true// const res = Object.is(null, null); //true// const res = Object.is(true, true); //true// const res = Object.is('1', '1'); //true// const res = Object.is(obj, obj); //true 同一引用// const res = Object.is({}, {}); //false 不同引用// const res = Object.is(1, 1); //true// const res = Object.is(+0, +0); //true// const res = Object.is(-0, -0); //true// console.log(res);//Object.is()的判断标准就是同值相等//-0 !== +0 -> 同值相等//NaN === NaN -> 同值相等//不进行隐式类型转换//-0 !== +0 -> 同值相等//NaN === NaN -> 同值相等
实现myIs()方法
//实现myIs方法Object.myIs = function (a, b) {if (a === b) {return a !== 0 || 1 / a === 1 / b;}return a !== a && b !== b;}console.log(Object.myIs(1, 1)); //trueconsole.log(Object.myIs({}, {})); //falseconsole.log(Object.myIs(+0, -0)); //falseconsole.log(1 / +0); //Infinityconsole.log(1 / -0); //-Infinityconsole.log('Infinity' === '-Infinity'); //falseconsole.log((1 / +0) === (1 / -0)); //falseconsole.log(Object.myIs(NaN, NaN)); //true
