数组的常见API方法 a. 其实就是ECMAScript提供的一套可以操作数组的方法 b. 语法: 数组.方法名() push() a. 语法: 数组.push(数据) b. 返回值: 返回写入数据后数组的长度 c. 作用: 将传入的数据写入数组的最后 d. 注意: 会修改原数组 unshift() a. 语法: 数组.unshift(数据) b. 返回值: 返回写入数据后数组的长度 c. 作用: 将传入的数据写入数组的最前面 d. 注意: 会修改原数组 pop() a. 语法: 数组.pop() b. 返回值: 返回删除的数组数据 c. 作用: 将数组的最后一个数据删除 d. 注意: 会修改原数组 shift() a. 语法: 数组.shift() b. 返回值: 返回删除的数组数据 c. 作用: 将数组的第一个数据删除 d. 注意: 会修改原数组 reverse() a. 语法: 数组.reverse() b. 作用: 将数组数据位置翻转 c. 返回值: 翻转后的数组 d. 注意: 会修改原数组 sort() a. 语法1: 数组.sort() ⅰ. 作用: 将数组的数据进行排序 注意: 数组数据大小是按位比较大小 ⅱ. 返回值: 排序后的数组 ⅲ. 注意: 会修改原数组 b. 语法2: 数组.sort(参数) ⅰ. 参数必须是一个函数,而且函数有两形参 该函数必须返回两个形参的差 ⅱ. 作用: 将数组的数据进行大小排序 如果传入函数返回值是 第一个参数减第二个参数的差则是升序排序 如果传入函数返回值是 第二个参数减第一个参数的差则是降序排序 ⅲ. 返回值: 排序后的数组 ⅳ. 注意: 会修改原数组 splice() a. 语法1: 数组.splice(起始索引,个数) ⅰ. 如果传递个数,则表示从起始索引到数组结束 ⅱ. 作用: 从起始索引开始删除数组数据 ⅲ. 返回值: 将删除的数据组成新数组并返回 ⅳ. 注意: 会修改原数组 b. 语法2: 数组.splice(起始索引,个数,写入数组数据,…) ⅰ. 作用: 从起始索引开始删除数组数据(如果个数为0则不删除) 然后从起始索引位置将第三个开始的参数写入数组 ⅱ. 返回值: 将删除的数据组成新数组并返回 ⅲ. 注意: 会修改原数组 数组塌陷 a. 当使用splice方法循环删除数组数据的时候 ⅰ. 会出现数组塌陷(数组长度发生变化,数据索引也变化) b. 解决方案1: 在splice删除后 循环变量i– c. 解决方案2: 倒序遍历 concat a. 语法: 数组.concat(参数) b. 作用: 将传入的参数合并到新数组 c. 返回值: 合并后的新数组 d. 不会改变原数组 join a. 语法: 数组.concat(连接字符) b. 作用: 根据传入的连接字符将数组数据拼接为字符串 ⅰ. 不传递参数,默认使用逗号拼接 c. 返回值: 拼接后的字符串 d. 不会改变原数组 e. 扩展: ⅰ. 数组的toString方法,其实就是调用了数组的join方法,将数组数据转给字符串 ⅱ. 而数组的toString方法是数组隐式转换为字符串使用的方法 includes a. 语法: 数组.includes(参数) b. 作用: 判断传入的参数是否在数组中存在 c. 返回值: 布尔值 d. 不会改变原数组 indexOf a. 语法1: 数组.indexOf(参数) ⅰ. 作用: 获取传入参数在数组中的索引,如果不存在则返回-1 ⅱ. 查找是从数组开始到结束的顺序检索,如果找到了则停止检索 b. 语法2: 数组.indexOf(参数,起始索引) ⅰ. 查找是从数组起始索引到结束的顺序检索,如果找到了则停止检索 ⅱ. 作用: 获取传入参数在数组中的索引,如果不存在则返回-1 ⅲ. 返回值: -1 或 索引 ⅳ. 不会改变原数组 lastIndexOf a. 语法1: 数组.lastIndexOf(参数) ⅰ. 作用: 获取传入参数在数组中的索引,如果不存在则返回-1 ⅱ. 查找是从数组结束位置到开头的顺序检索,如果找到了则停止检索 b. 语法2:数组.lastIndexOf(参数,起始索引) ⅰ. 查找是从数组起始索引到开头的顺序检索,如果找到了则停止检索 ⅱ. 作用: 获取传入参数在数组中的索引,如果不存在则返回-1 c. 返回值: -1 或 索引 d. 不会改变原数组 slice a. 语法: 数组.slice(起始索引,结束索引) b. 作用: 从数组的起始索引到结束索引 截取数组数据组成 新的数组返回 ⅰ. 包前不包后(包含起始索引,不包含结束索引) c. 返回值: 截取的数据组成的新数组 d. 不会改变原数组 at a. 语法: 数组.at(索引) b. 作用: 根据传入的索引返回对应数据 ⅰ. 索引可以是负数: -1 表示最后一个 -2 倒数第二个 c. 返回值: 数组数据,如果不存在返回undefined d. 不会改变原数组 copyWithin a. 语法: 数组.copyWithin(放置的起始索引,复制的起始索引,复制结束索引) ⅰ. 包前不包后 ⅱ. 作用: 复制数组中的某一个段数据并返回到数组中 注意: 数组长度不会发生变化 ⅲ. 返回值: 改变后的数组 ⅳ. 会改变原数组 fill a. 语法: 数组.fill(数据,起始索引,结束索引) b. 作用: 将传入的数据从起始索引到结束索引进行填充 ⅰ. 不写 起始索引 从0开始 ⅱ. 不写 结束索引 填充到结束 c. 返回值: 改变后的数组 d. 会改变原数组 flat a. 语法: 数组.flat(数值) b. 作用: 根据传入的数据 将多维数组拍平几层 ⅰ. 传入Infinity 则不管是几维数组都全部拍平 c. 返回值: 改变后的数组 d. 不会改变原数组 数组去重 a. 使用set集合数据来去重 b. 创建一个新数组,判断arr中的每一个数据在新数组中是否存在,不存在则写入新数组 c. 利用对象的属性名唯一的特性 d. 还有一些!!! 数组遍历方法 forEach
语法: 数组.forEach(function(item,index,arr){}) + 执行过程: 传入的函数执行次数是数组的长度 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 遍历数组 - 返回值: undefined
map
语法: 数组.map(function(item,index,arr){}) + 执行过程: 传入的函数执行次数是数组的长度 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 映射数组 - 返回值: + 返回值一个新数组,新数组的数据是每次函数执行的结果组成
filter
语法: 数组.filter(function(item,index,arr){}) + 执行过程: 传入的函数执行次数是数组的长度 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 过滤数组 - 返回值: + 返回值一个新数组,新数组的数据是 每次函数执行结果为true(隐式转布尔true也是一样) 对应的原数组数据
every
语法: 数组.every(function(item,index,arr){}) + 执行过程: - 如果函数返回值为false,则函数不在继续依次执行 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 判断数组 - 返回值: 布尔值 + 如果传入的函数执行每次返回值都是布尔值true(隐式转化也行),则every方法执行的结果是true + 如果传入的函数执行某一次返回值都是布尔值false(隐式转化也行),则every方法执行的结果是false
some
语法: 数组.some(function(item,index,arr){}) + 执行过程: - 如果函数返回值为true,则函数不在继续依次执行 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 判断数组 - 返回值: 布尔值 + 如果传入的函数执行每次返回值都是布尔值false(隐式转化也行),则some方法执行的结果是false + 如果传入的函数执行某一次返回值都是布尔值true(隐式转化也行),则some方法执行的结果是true
find
语法: 数组.find(function(item,index,arr){}) + 执行过程: - 如果函数返回值为true,则函数不在继续依次执行 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 查找数组 - 返回值: 满足条件的数组元素或undefined
findIndex
语法: 数组.findIndex(function(item,index,arr){}) + 执行过程: - 如果函数返回值为true,则函数不在继续依次执行 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 查找数组 - 返回值: 满足条件的数组元素对应索引或-1
findLast
语法: 数组.findLast(function(item,index,arr){}) + 执行过程: - 从数组元素的后往前的元素一次执行函数, - 如果函数执行结果为true则函数不再依次执行 + 函数中有三个形参 + item: 每次函数执行数组的元素 + index: 每次函数执行数组元素的索引 + arr: 数组本身 - 查找数组 - 返回值: 找到最后一个满足条件的数组元素 或 undefined
reduce
语法1: 数组.reduce(function(prev,item,index,arr){}) + 执行过程: 传入的函数执行次数是数组的长度-1 + 函数中有四个形参 + prev: 第一次函数执行prev表示数组的第一个元素 - 第二次往后函数执行prev都是上一次函数执行的结果 + item: 第一次函数执行item表示数组的第二个元素 - 第二次往后函数执行item表示数组依次的元素 + index: 每次函数执行数组item元素的索引 + arr: 数组本身 + 累计数组 + 返回值: 函数最后一次执行返回的结果就是reduce的返回值 语法2: 数组.reduce(function(prev,item,index,arr){},init) + 执行过程: 传入的函数执行次数是数组的长度 + 函数中有四个形参 + prev: 第一次函数执行prev表示init - 第二次往后函数执行prev都是上一次函数执行的结果 + item: 每次函数执行数组的元素 + index: 每次函数执行数组item元素的索引 + arr: 数组本身 + 累计数组 + 返回值: 函数最后一次执行返回的结果就是reduce的返回值
reduceRight
和reduce用法一模一样 - 区别: + reduce执行函数是从数组的第一个元素开始到最后一个元素结束 + reduceRight执行函数是从数组的最后一个元素开始到第一个元素结束
回调函数
a函数当做参数传递给b函数 - 在b函数内,a函数以形参调用了 - 那么我们将a函数叫做 回调函数 调用函数的作用 - 封装异步代码函数时候,需要使用回调函数 - 封装遍历操作的时候,也会用到回调函数 + 遍历操作其实就是 需要多次做的事情(重复执行的代码)
数组方法:
使用方式 + 数组.方法名() 重构的方法需要写到 数组空间
Array.prototype中 重构数组遍历方法 回调函数执行次数需要 根据调用方法的数组决定 - 函数内的this关键字 指向 调用这个方法的数组 我们在全局中直接定义函数,数组无法直接调用 - 会报错: arr.fn is not a function 数组的API方法都是在 数组空间
中 - 在这个数组空间
中的方法,数组都可以直接使用 - 这个 数组空间
是 Array.prototype,是一个对象 - 如果我们将自己定义的函数 添加到这个 数组空间
中 - 那么数组就可以直接调用我们定义的函数了
/* 我们在全局中直接定义函数,数组无法直接调用- 会报错: arr.fn is not a function数组的API方法都是在 `数组空间`中- 在这个`数组空间`中的方法,数组都可以直接使用- 这个 `数组空间` 是 Array.prototype,是一个对象- 如果我们将自己定义的函数 添加到这个 `数组空间`中- 那么数组就可以直接调用我们定义的函数了 */function myforEach(cb) {// cb接受传入的回调函数// 多次执行cb函数---根据arr1数组的长度// 此处的this关键字指向调用 方法的数组// 遍历this数组来执行cb函数for (var i = 0; i < this.length; i++) {// 调用cb// cb的第一个参数是数组元素// cb的第二个参数是数组元素的索引// cb的第三个参数是原数组(调用方法的数组本身)cb(this[i],i,this); } }// 将myforEach添加到 `数组空间` 中Array.prototype.myforEach = myforEach;// 数组可以直接调用myforEach方法var arr1 = ['a','b','c'];arr1.myforEach(function (item,index,arr2) {console.log( item,index,arr2 )})var arr3 = [1,2,3,4,5];arr3.myforEach(function (item,index,arr2) {document.write(item);})
重构map方法
// 将自定义的方法写到 `数组空间` Array.prototype.myMap = function (cb) {var newArr = []; // 作为myMap的返回值数组// 遍历数组for (var i = 0; i < this.length; i++) {// 将回调函数的结果作为 newArr数组的数据写入var r = cb(this[i], i, this)newArr.push(r);}return newArr;}// // 将来使用的时候// var arr1 = [10, 20, 30];// var resArr = arr1.myMap(function (item, index, arr) {// // console.log( item, index, arr )// return item*.3;// })// console.log(resArr)
重构数组的 filter 方法
filter方法传入的函数需要执行 数组的长度 次 - filter返回值: + 是一个新数组 + 新数组中的数据 是传入的函数执行后返回值为true 对应的数组元素 代码
Array.prototype.myFilter = function (cb) {var newArr = [];// 遍历this数组for (var i = 0; i < this.length; i++) {var flag = cb(this[i], i, this);// 判断flag是否为true 将this[i]数组元素添加到newArrif (flag) newArr.push(this[i]);}return newArr;}// 使用我们重构的方法var arr1 = [10, 20, 30];var resArr = arr1.myFilter(function f1(item, index, arr) {return item < 50;})console.log(resArr);
重构every方法
返回值是 布尔值 - 根据传入函数执行的返回值来决定 + 如果某一个元素执行传入的函数返回值是false则最终结果是false + 每一个元素执行传入函数返回值都是true则最终结果是true 代码
Array.prototype.myEvery = function (cb) {for (let i = 0; i < this.length; i++) {var r = cb(this[i], i, this);if (!r) return false;}// 循环调用 回调函数 完毕 代码还没执行结束return true}// 使用myEvery方法var res = [1, 2, 3].myEvery(function f1(item) {console.log( item )return item < 2})console.log( res )
重构some方法
返回值是 布尔值 - 根据传入函数执行的返回值来决定 + 如果某一个元素执行传入的函数返回值是true则最终结果是true + 每一个元素执行传入函数返回值都是false则最终结果是false 代码
Array.prototype.mySome = function (cb) {for (let i = 0; i < this.length; i++) {var r = cb(this[i], i, this);if (r) return true;}// 循环调用 回调函数 完毕 代码还没执行结束return false}// 使用mySome方法var res = [1, 2, 3].mySome(function f1(item) {console.log(item)return item < 2})console.log(res)
排序三个算法: 计数算法 数组的排序算法–计数 - 将需要排序的数组数据 作为新数组的索引使用 + 数组的索引是 0开始的连续自然数 - 将新数组中的有数据的索引取出写回到数组中 代码
// 准备一个新数组var newArr = [];// 遍历arr将arr中的数据作为newArr的索引使用for (var i = 0; i < arr.length; i++) {newArr[arr[i]]?newArr[arr[i]]++:newArr[arr[i]] = 1}// console.log( newArr )// 将arr数组清空arr.length = 0;// 遍历newArr取出索引for (var j = 0; j < newArr.length; j++) {// j就是newArr的索引if(!newArr[j]) continue; //没有值的索引我们不要for (var k = 0; k < newArr[j]; k++) {arr.push(j);// 将j写入}}console.log( arr )
插入算法 插入排序 - 取出一个数组数据,逐个和前一前面的数据比较大小 - 如果某一个数据更大,则将该数据赋值给后一个位置 - 比较完毕,将取出的这个数组放到比这个数小的后面位置
// 遍历arr数组for (var i = 1; i < arr.length; i++) {var tmp = arr[i];var j = i - 1;// arr[i]前一个数据开始倒序遍历while (arr[j] > tmp) {// 将arr[j]的数据 放到后面一个位置arr[j+1] = arr[j];j--;}// 放while循环结束的时候// arr[j] > tmp===>false// arr[j] <= tmp-->我们需要将tmp放到j+1arr[j+1] = tmp;}
快速排序 数组排序–快排(递归二分法) + 利用了递归函数 + 二分: 先取出数组中的中间数center - 然后遍历数组,将比中间数更大的放到一个big数组 + 将比中间数更小的放到一个small数组 - 然后继续将small 和big 数组进行递归二分 + 并且在递归中返回直接 [small] center [big] 的合并
function quickSort(arr) {// 1. 折返点if(arr.length == 1|| arr.length ==0) return arr;// 2.0 数组二分// 获取中间数的索引var centerIndex = parseInt(arr.length/2);// 因为从arr中取出的中间数,不在需要和本身比较,使用splice获取// 注意:splice返回值是一个数组var center = arr.splice(centerIndex,1)[0];// 准备大小数组var small = [];var big = [];// 遍历arr数组 判断数值大小for (var i = 0; i < arr.length; i++) {center>arr[i]?small.push(arr[i]):big.push(arr[i]); }// 2. 递进关系--->大小数组都需要继续二分递归return [].concat(quickSort(small),center,quickSort(big));} console.log( quickSort(arr) )