- 数组的常见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]数组元素添加到newArr
if (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+1
arr[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) )