javascript基础学习
冒泡排序
-
意义:是吧一个乱序的数组通过代码执行,排成有序的数组
-
准备原始数组
-
var arr = [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ] // 目的: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] console.log('原始数组 : ', arr)
-
冒泡排序, 是若干数组排序算法的一种
-
逻辑:
1 | 遍历数组, 两两对比, 把相对较大的数字向后移动 |
---|---|
2 | 遍历一遍以后, 得到的结果就是最大的数字一定在最后面 |
3 | 重复步骤1, 继续比较, 两轮以后, 最大的两个数字一定在最后两个位置 |
4 | 不管多少个数字, 只要比较总长度 -1 轮, 那么数组就排序完成了 |
步骤一
交换 [0] 和 [1] 位置的数据
var tmp = arr[0]
arr[0] = arr[1]
arr[1] = tmp
tmp = null
console.log('交换完毕 : ', arr)
步骤二:
交换 [0] 和 [1] 位置的数据
var tmp = arr[0]
arr[0] = arr[1]
arr[1] = tmp
tmp = null
console.log('交换完毕 : ', arr)
-
问题:如何判断出本轮全是 false
1 就看 if 内的代码是否有执行过 2 因为只有 true 的时候才会执行 if 内的代码 3 如果这一轮之内, if 内的代码从来没有执行过, 那么就是全 false 4 在此之后的所有内容都不需要了
计数排序
- 计数排序: 数组排序算法的一种
-
逻辑:
-
准备一个新的数组
=> 遍历原始数组, 把原始数字当做新数组的索引向新数组内填充数据
=> 新数组的数据按照计数排列 -
遍历新数组
=> 把索引在当做数据放进原始数组内
=> 前提: 把原始数组清空-
代码
-
准备一个原始数组
var origin = [ 9, 3, 100, 6, 4, 100, 1, 9, 8, 7, 2, 2, 5, 100, 3, 32, 55 ] console.log('原始数组 : ', origin) //准备一个新数组 var newarr = []
-
步骤2: 把新数组内的索引, 当做数据还原到 origin 内, 把 新数组内的值, 当做个数插入
// // 归零 origin
// origin.length = 0
// console.log('origin 归零 : ', origin) -
for (var i = 0; i < newarr.length; i++) { // // 2-1. 如果当前 [i] 位置没有数据, 那么循环的本次不需要了 if (!newarr[i]) continue // // 2-2. 把有数据位置的索引 i 当做真实数据, 追加到 origin 内 // // 问题: 所有的都直接追加吗 ? // // 值为 1 的, 直接追加, 否则的话, 值是多少, 追加多少个 if (newarr[i] === 1) { origin[origin.length] = i } else { // // 值是多少, 追加多少个, 循环来追加 // // 问题: 循环多少次, 值是多少, 循环多少次 for (var k = 0; k < newarr[i]; k++) { origin[origin.length] = i } } console.log(i) } for (var i = 0; i < newarr.length; i++) { // // 2-1. 如果当前 [i] 位置没有数据, 那么循环的本次不需要了 if (!newarr[i]) continue // // 2-2. 把有数据位置的索引 i 当做真实数据, 追加到 origin 内 // // 当前这个索引位置上的值是多少, 就向 origin 内追加多少个当前索引数字 for (var k = 0; k < newarr[i]; k++) origin[origin.length] = i } console.log('排序之后 : ', origin)
-
计数排序
var origin = [ 10,20,30,40,50,60,70,10,30,40,50 ] var newarr = [] // 1. 把数据当索引 for (var i = 0; i < origin.length; i++) { // origin[i] 就是数据 newarr[ origin[i] ] ? newarr[ origin[i] ]++ : newarr[ origin[i] ] = 1 } // 2. newarr 中的索引当数据 // newarr 中的值当多少个 // 2-1. 清空 origin origin.length = 0 // 2-2. 填充回去 for (var i = 0; i < newarr.length; i++) { // i 表示真实数据 // newarr[i] 表示有多少个 if (!newarr[i]) continue // 填充回去 // 填充 newarr[i] 个 i for (var k = 0; k < newarr[i]; k++) origin[origin.length] = i } origin.push([) console.log('排序之后 : ', origin)
-
/ 问题: 如何判断一个数组内有没有某一个索引位置的数据 ?
// 索引可以访问数组内的数据
// 如果有该索引位置, 那么就是该索引位置的数据
// 如果没有该索引位置, 那么就是 undefined
// 根据我的设置
// 原先有就是 ++, 原先没有就是 = 1
// 如果我拿到数组内某一个索引位置是 undefined, 说明之前没有过
// 只要之前有过, 那么一定是一个正整数
// console.log(newarr[1])
// if (newarr[1] === undefined) newarr[1] = 1
// else newarr[1]++
// console.log(newarr) -
逻辑
-
// 逻辑 var origin = [ 2, 3, 2, 6, 5] console.log(origin) var newarr = [] newarr[2] = 1 newarr[3] = 1 newarr[2]++ newarr[6] = 1 newarr[5] = 1 console.log(newarr) origin = [] console.log(origin) origin[origin.length] = 2 origin[origin.length] = 2 origin[origin.length] = 3 origin[origin.length] = 5 origin[origin.length] = 6 console.log(origin)
-
-
-
-
选择器
-
选择排序
-
1 遍历数组, 找到数组中最小的数字, 和最前面一个数字对调 2 从第二轮开始, 跳过第一个, 剩下的再继续重复步骤 -
第 x 轮 外层循环控制变量 假设 里层循环开始 对调 1 0 0 1 [0] 和 [minIndex] 2 1 1 2 [2] 和 [minIndex] 3 2 2 3 [3] 和 [minIndex] -
代码
- 步骤一
// 1-1. 遍历找到最小的数字的索引 // // 假设 [0] 位置数据最小 var minIndex = 0 // // 遍历数组进行比较 for (var i = 1; i < arr.length; i++) { // // 开始比较, 依次把 arr[i] 和 arr[minIndex] 比较 if (arr[i] < arr[minIndex]) minIndex = i // } // // 循环完毕以后, minIndex 就是最小数字的索引 // // 就把 [minIndex] 位置和 [0] 位置的数据进行对调 // // 问题: 每一次都必须要对调吗 ? 如果 minIndex === 0 不需要对调了 if (minIndex !== 0) { var tmp = arr[0] arr[0] = arr[minIndex] arr[minIndex] = tmp tmp = null } console.log('排序一次 : ', arr)
-
步骤二
// 假设 9 个数字, 比较多少轮 ? 8 轮 for (var j = 0; j < arr.length - 1; j++) { // 完整书写步骤1 // 假设 var minIndex = j // 里层循环开始 for (var i = j + 1; i < arr.length; i++) { if (arr[i] < arr[minIndex]) minIndex = i } // 对调 if (j === minIndex) continue // 代码执行到这里, 说明 j 和 minIndex 不一样 var tmp = arr[j] arr[j] = arr[minIndex] arr[minIndex] = tmp tmp = null } console.log('排序之后 : ', arr)
-
数组常用方法
-
数组常用方法
+ 什么是数组常用方法
+ JS 提供给我们专门用来操作数组的方法
+ 因为数组本身的特性决定了 好加不好去, 不好插入
+ 语法特点: 数组.方法名(参数)
=> 不同的方法, 就是方法名和参数不一样 -
push()
=> 语法:
-> 数组.push(数据)
-> 数组.push(数据, 数据2, 数据3, 数据4, …)
=> 作用: 按照顺序向数组的后面追加你插入的数据
=> 返回值: 追加数据以后, 数组最新的长度2. pop() => 语法: 数组.pop() => 作用: 删除数组的最后一个数据 => 返回值: 被删除的数据 3. unshift() => 语法: -> 数组.unshift(数据) -> 数组.unshift(数据, 数据2, 数据3, 数据4, ...) => 作用: 按照顺序向数组的最前面插入数据 => 返回值: 插入数据以后, 数组最新的长度 4. shift() => 语法: 数组.shift() => 作用: 删除数组最前面一个数据 => 返回值: 被删除的数据
-
var arr = [ ‘hello’, ‘world’, ‘你好’, ‘世界’ ]
console.log('原始数组 : ', arr)// 1. push()
// 开始追加
// var res = arr.push(‘新来的’)
// var res = arr.push(‘新来的’, 100, 200)
// console.log('追加以后 : ', arr)
// console.log('返回值 : ', res)// 2. pop()
// 开始删除
// var res = arr.pop()
// console.log('删除以后 : ', arr)
// console.log('返回值 : ', res)// 3. unshift()
// var res = arr.unshift(‘新来的’)
// var res = arr.unshift(‘新来的’, 100, 200)
// console.log('插入以后 : ', arr)
// console.log('返回值 : ', res)// 4. shift()
// var res = arr.shift()
// console.log('删除之后 : ', arr)
// console.log('返回值 : ', res) -
var arr = [10, 20, 30, 40, 50, 60]
// // 直接修改 length 去掉的是后面的
// // 只能从第 2 个开始, 依次向前覆盖
// // 最后得到的结果是最后一个重复的
// // 此时在去掉最后一个
// for (var i = 0; i < arr.length - 1; i++) {
// // 当前这个被赋值为后一个数据内容
// arr[i] = arr[i + 1]
// }
// arr.length–// console.log(arr)
-
数组常用方法
5. reverse() => 语法: 数组.reverse() => 作用: 反转数组 => 返回值: 反转以后的数组 6. sort() => 语法: -> 数组.sort() + 一位一位看待按照 ascii 码表的顺序进行排列 -> 数组.sort(function (a, b) { return a - b }) + 按照数字从小到大排列 -> 数组.sort(function (a, b) { return b - a }) + 按照数字从大到小排列 => 作用: 数组排序 => 返回值: 排序好的数组 7. splice() => 语法: -> 数组.splice(开始索引, 多少个) -> 数组.splice(开始索引, 多少个, 数据1, 数据2, 数据3, ...) + 按照顺序把要插入的内容插入到数组截取位置 + 注意: 从哪截取, 从哪插入 => 作用: 从原始数组内截取部分数据, 并插入新数据(可以选择性插入) => 返回值: 必然是一个新的数组 -> 新数组内按照顺序存储的你截取下来的内容 -> 如果你没有截取, 那么就是一个空的数组
*/
var arr = [ 1, 6, 4, 2, 9, 5, 7, 3, 8, 11, 22, 17, 10, 35, 21, 100 ]
console.log('原始数组 : ', arr)// 5. reverse()
// var res = arr.reverse()
// console.log('反转之后 : ', arr)
// console.log('返回值 : ', res)
// 复杂数据类型之间的比较, 是比较地址// 6. sort
// 语法1:
// var res = arr.sort()
// console.log('排序之后 : ', arr)
// 语法2:
// var res = arr.sort(function (a, b) { return a - b })
// console.log('排序之后 : ', arr)
语法3:
// var res = arr.sort(function (a, b) { return b - a })
// console.log('排序之后 : ', arr)
// console.log('返回值: ', res)// 7. splice()
var arr = [ 100, 200, 300, 400, 500, 600 ]
// 0 1 2 3 4 5
console.log('原始数组 : ', arr)
// 语法1:
// 从 [2] 开始截取 3 个 数据
// var res = arr.splice(2, 3)
// console.log('截取之后 : ', arr)
// console.log('返回值 : ', res)// 语法2:
// 从 [2] 开始截取 1 个数据, 把 ‘新来的’ 插入到 [2] 位置
// var res = arr.splice(2, 1, ‘新来的’)// 从 [2] 开始截取 0 个数据, 把 ‘新来的’ 插入到 [2] 位置, 从原先的 [2] 位置数据向后顺延
// var res = arr.splice(2, 0, ‘新来的’)// 从 [2] 开始截取 1 个数据, 把 '‘新来的’, ‘又一个’, ‘还一个’ 按照顺序插入到 [2] [3] [4] 的位置, 其余的向后顺延
var res = arr.splice(2, 1, ‘新来的’, ‘又一个’, ‘还一个’)
console.log('截取之后 : ', arr)
console.log('返回值 : ', res)
数组塌陷
-
/*
数组塌陷
+ 当你删除数组前面的数据的时候
+ 从你删除位置的数据开始, 后面的所有数据, 索引会先前递减
+ 我们管这个行为叫做 数组塌陷
*/// 需求: 数组 4 个数据, 遍历每次删除当前这个, 一次一个, 删除完毕数组
var arr = [ 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4 ]
console.log('原始数组 : ', arr)// 出现塌陷问题
// for (var i = 0; i < arr.length; i++) {
// // i 就是当前这个数据的索引
// // aplice(开始索引, 多少个)
// arr.splice(i, 1)
// }/*
分析问题开始循环 1. i === 0, len === 4, 条件为 true arr.splice(0, 1) 删除之后 [ 2, 3, 4 ] i++ 2. i === 1, len === 3, 条件为 true arr.splice(1, 1) 删除之后 [ 2, 4 ] i++ 3. i === 2, len === 2, 条件为 false 结束循环 解决问题的方向 1. 不要塌陷: 从后面删除, 倒着循环数组 2. 让循环控制变量退一步: i--
*/
// 解决塌陷方案1
// 倒着循环数组
// for (var i = arr.length - 1; i >= 0; i–) {
// // i 依旧是数组内每一个的索引, 只不过是倒着的
// arr.splice(i, 1)
// }/*
分析问题1. i === 3; i >= 0; 条件为 true arr.splice(3, 1) 删除之后, [1, 2, 3] i-- 2. i === 2; i >= 0; 条件为 true arr.splice(2, 1) 删除之后, [ 1, 2 ] i-- 3. i === 1; i >= 0; 条件为 true arr.splice(1, 1) 删除之后, [ 1 ] i-- 4. i === 0; i >= 0; 条件为 true arr.splice(0, 1) 删除之后, [] i-- 5. i === -1; i >= 0; 条件为 false 循环结束
*/
// 解决塌陷方案2:
// i–
// 只要你执行了 splice, 就执行一个 i–
for (var i = 0; i < arr.length; i++) {
if (arr[i] % 2) {
arr.splice(i, 1)
i–
}
}/*
分析问题1. i === 0; i < 4; 条件为 true arr.splice(0, 1) 删除之后 [ 2, 3, 4 ] i-- i++ 2. i === 0; i < 3; 条件为 true arr.splice(0, 1) 删除之后 [ 3, 4 ] i-- i++ 3. i === 0; i < 2; 条件为 true arr.splice(0, 1) 删除之后 [ 4 ] i-- i++ 4. i === 0; i < 1; 条件为 true arr.splice(0, 1) 删除之后 [] i-- i++ 5. i === 0; i < 0; 条件为 false 结束循环
*/
console.log('删除之后 : ', arr)
数组去重
-
/*
数组去重 : 去除数组内重复项
*/// 原始数组 // var arr = [ 1, 2, 3, 4, 3, 2, 1, 3, 4, 2, 1, 5, 6, 4, 3, 2, 5 ] // console.log('原始数组 : ', arr) // 方案1: // 拿到第一个和后面进行比较, 如果有一样的就删除一个 // for (var i = 0; i < arr.length; i++) { // // arr[i] 就是数组内的每一个数据 // // arr[0] === 1 // // 从 [1] 开始向后查找, 只要后面还有 1 这个数据, 那么把后面的删除了 // // 不确定后面还有几个 1, 只要有一个就要删除一个 // // 当后面还有 1 的时候, 就删除一个, 否则继续循环 i++ // var n = i + 1 // while (n < arr.length) { // if (arr[i] === arr[n]) { // arr.splice(n, 1) // i-- // } // n++ // } // } // 方案2: // includes() // 语法: 数组.includes(数据) // 作用: 判断数组内是否有该数据 // 返回值: 布尔值 // true, 说明有 // false, 说明没有 // 准备一个空数组 // 把原始数组进行遍历, 依次插入到新数组内 // 在插入之前进行一个判断, 新数组内有这个数据, 就不插入, 没有才插入 // var newarr = [] // for (var i = 0; i < arr.length; i++) { // // arr[i] 是数组内的每一个数据 // // 如果从 arr[1] 开始后面还有 1 这个数据, 那么删除一个 // if (!newarr.includes( arr[i] )) { // newarr.push(arr[i]) // } // } // console.log('去重之后 : ', newarr) // 方案3: // 计数排序前半部分 + 遍历新数组, 每个索引插入一个 // var arr = [ 1, 2, 3, 4, 3, 2, 1, 3, 4, 2, 1, 5, 6, 4, 3, 2, 5, 9 ] // console.log('原始数组 : ', arr) // var newarr = [] // for (var i = 0; i < arr.length; i++) newarr[ arr[i] ] = arr[i] // // 把 newarr 中为 undefined 的干掉 // for (var i = 0; i < newarr.length; i++) { // if (!newarr[i]) { // newarr.splice(i, 1) // i-- // } // } // console.log(newarr) // 方案4: // 使用 sort 排序 // 判断紧挨着的两个是否一样, 如果一样, 删除一个 // var arr = [ 1, 2, 3, 4, 10, 3, 2, 11, 1, 3, 4, 2, 11, 1, 10, 5, 6, 4, 3, 2, 5, 9 ] // console.log('原始数组 : ', arr) // arr.sort() // console.log('排序之后 : ', arr) // // 遍历 // for (var i = 0; i < arr.length; i++) { // // 判断当前和下一个一样 // if (arr[i] === arr[i + 1]) { // arr.splice(i, 1) // i-- // } // } // console.log('去重之后 : ', arr) // 方案5: 和方案3一致, 使用对象 // var arr = [ 1, 2, 3, 4, 10, 3, 2, 11, 1, 3, 4, 2, 11, 1, 10, 5, 6, 4, 3, 2, 5, 9 ] // console.log('原始数组 : ', arr) // 准备一个新的对象 // var obj = {} // for (var i = 0; i < arr.length; i++) obj[ arr[i] ] = '随便' // // 把对象内的每一个索引当做 数据 插入到数组内 // var newarr = [] // for (var k in obj) { // newarr.push(k - 0) // } // console.log(newarr) // 6. Set() // Set 是一个 js 内的数据结构, 长得和数组差不多 // 特点: 不接受重复数据 // 语法: // 创建空 Set: var s = new Set() // var s = new Set() // console.log(s) // 创建带有数据的 Set: var s = new Set([ 数据1, 数据2, 数据3 ]) // var s = new Set([ 1, 2, 3, 1, 2, 3 ]) // console.log(s) var arr = [ 1, 2, 3, 4, 10, 3, 2, 11, 1, 3, 4, 2, 11, 1, 10, 5, 6, 4, 3, 2, 5, 9 ] console.log('原始数组 : ', arr) // 利用 Set 数据结构 // var s = new Set(arr) // console.log(s) // // 把 Set 数据结构转换会数组数据类型 // // 方法1: Array.from() // var res1 = Array.from(s) // console.log(res1) // // 方案2: 展开运算符(...) // var res2 = [ ...s ] // console.log(res2) var r1 = Array.from( new Set(arr) ) console.log(r1) var r2 = [ ...new Set(arr) ] console.log(r2)
函数回调
-
/*
回调函数 callback
+ 概念: 把 函数A 当做实参传递到 函数B 内
在 函数B 内以形参的方式调用 函数A
此时, 我们就说 函数A 是 函数B 的回调函数
+ 作用:
1. 封装和遍历相关的内容
2. 封装和异步相关的内容思考: + 封装: 为了把一个内容(行为) 放在一个函数内, 为了复用(灵活的复用) + 遍历: 使用循环从头到尾的获取到数组内的每一个数据 => 我随着循环, 每次都做一样的事情, 但是可能有细节不一样 例子: + 你作为我封装的一个对象 + 功能: 跑腿
*/
// function a(cb) {
// // 这里的 cb 形参接受的就是全局函数 b 的存储地址
// // 此时这里的形参 cb 和全局变量 b 操作的是一个函数地址
// // cb() // 等价于在调用 全局b 函数// for (var i = 0; i < 10; i++) {
// cb()
// }
// }// function b() {
// console.log(‘我是全局 b 函数’)
// // 在这里做出你每次想做的事情就可以了
// }// // 把 b 函数当做参数传递到 a 函数内了
// // 变量 b 保存的是 一个函数的地址
// // 这里当做实参传递进去的也就是一个函数的地址
// a(b)function sort(cb) {
var arr = [ 10, 20, 30, 40, 50 ]
for (var i = 0; i < arr.length - 1; i++) {
// 此时的 cb 就是在调用 b 函数
// cb() 函数调用阶段, 书写的叫做实参
var res = cb(arr[i], arr[i + 1])
if (res >= 0) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
}
}
}
// // 这个 b 函数的调用, 就是写在 sort 函数内 cb(arr[i], arr[i + 1])
// // 所以这里 return 出去的内容, 就应该再 cb 前面接受返回值
// sort(function b(param1, param2) { return param2 - param1 })
数组常用办法forEach
-
/*
数组常用方法3
+ forEach()
+ 专门用来遍历数组的方法语法: => 数组.forEach(function (item, index, arr) { item 表示数组的每一项 index 表示数组每一项的索引 arr 表示原始数组 }) 返回值: => 没有, undefined 意义: 用来遍历数组 */ // var arr = [ 100, 200, 300, 400, 500, 600 ] // var arr2 = [ 10, 20, 30, 40 ] // a 会根据数组内有多少数据, 执行多少回 // arr.forEach(function a(item, index, arr) { // console.log('我执行了', item, index, arr) // // 可以直接书写每一次循环你要做的事情 // }) // 我自己模仿一个 forEach 方法 // function myForEach(cb) { // // 需要在这里直到是谁调用了我 // // 我就去遍历谁 // // console.log('我被谁调用了呢 ? ', this) // // 只需要遍历 this // for (var i = 0; i < this.length; i++) { // // 在循环内, this[i] 是当前这个数组的每一项 // // 在循环内, i 是当前这个数组每一项的索引 // // 在循环内, this 就是当前这个数组 // cb(this[i], i, this) // } // } // 1. 能不能像 forEach 一样直接被 数组.myForEach 调用 // 需要让我封装的方法能被数组直接调用 // 需要把这个方法赋值给一个 "空间" 内 // 把我们自己写的 myForEach 放在 "数组方法空间" 内 // "数组方法空间" 是一个对象数据类型 // "数组方法空间" 被我们叫做 Array.prototype // Array.prototype.myForEach = myForEach // var arr = [ 10, 20 ] // arr.myForEach() // arr.myForEach(function (item, index, arr) { console.log('我是 arr 调用', item, index, arr) }) // arr2.myForEach() // 求 arr 数组内每一项的和 // 在循环内做的事情: 把每一项叠加在一个初始变量身上 // var sum = 0 // arr.myForEach(function (item) { // sum += item // }) // console.log(sum) // 2. forEach 是用来遍历数组的 // 在 myForEach 内也需要可以遍历数组 // 遍历的不是我随便定义的数组, 而是哪一个数组调用我, 我遍历谁 // a1.forEach() 在 forEach 内遍历 a1 数组 // a2.forEach() 在 forEach 内遍历 a2 数组 // a2.myForEach() 在 myForEach 内遍历 a2 数组 // 在我封装的方法内直到, 是哪一个数组在调用我 // 在函数内有一个关键字, 叫做 this // 今天: 哪一个数组调用这个方法, 方法内的 this 就是谁 // 例子: 现在有一个对象叫做 obj var obj = {} var name = 'Jack' console.log(obj) // 需要把 myForEach 放在 obj 内 obj.myForEach = myForEach // 需要把一个 name 放在对象内 obj.name = name console.log(obj) // 1. 需要封装一个方法, 让数组可以直接调用 var arr = [ 100, 200, 300, 400 ] // 需要把这个方法放在 Array.prototype 这个对象内 Array.prototype.myForEach = myForEach function myForEach(cb) { // 2. 在我们封装好的函数内, this 就是调用我的那个数组 // 遍历 this for (var i = 0; i < this.length; i++) { // 循环遍历多少遍, 就把锦囊执行多少遍 // 在调用锦囊的时候, 把 数组的每一项 索引 原始数组 给到锦囊内部 cb(this[i], i, this) } } arr.myForEach(function (item, index, arr) { console.log('锦囊妙计', item, index, arr) })
数组常用办法map
-
/*
封装一个方法 - abc
+ 需求:
=> 根据原始数组的长度 返回 给我一个新的数组
=> 在回调函数内可以对原始数组内每一个数据进行操作(我需要的操作)
=> 新数组内得到数据, 就是操作以后的数据数组常用方法 - map + 语法: 数组.map(function (item, index, arr) {}) + 作用: 对原始数组进行映射 + 返回值: 就是一个和原始数组一样长度的新数组, 并且内部的数据是被映射操作过的内容 */ var arr = [ 10, 20, 30, 40 ] var res = arr.map(function (item) { return item * 10 }) console.log(arr) console.log(res) // 1. 准备方法 // Array.prototype.abc = abc // function abc(cb) { // // 根据需求1 // // 必须要建立一个新数组了 // var ary = [] // // 我们需要根据原始数组(this) 的长度和 cb 的操作 // // 向 ary 内添加数据 // for (var i = 0; i < this.length; i++) { // // 使用 abc 方法的人, 会把他想要的操作条件写在 aaa 内 // // 需要调用 cb, 并且把每一项给到 aaa 函数 // // r 接受到的及时 aaa 函数内的返回值 // // 因为 aaa 内返回的是 每一项的 * 10 的结果 // // r 得到的就是每一项 * 10 的结果 // var r = cb(this[i], i, this) // ary.push(r) // } // // 把操作好的数据返回 // return ary // } // // 2. 将来使用的时候 // var arr = [ 10, 20, 30, 40, 60, 80 ] // console.log('原始数组 : ', arr) // var res = arr.abc(function aaa(item, index, arr) { // // 一些操作, 假设我的操作是 * 10 // // 以返回值的形式把结果给出去 // return item * 10 + 345 // }) // console.log(res) // res === [ 100, 200, 300, 400 ]
数组常用办法filter
-
/*
封装方法
+ 需求: 根据我的条件对原始数组进行过滤, 把原始数组中满足我条件的所有项拿出来
组成一个新的数组返回
+ 例子:
=> 原始数组 [ 10, 20, 30, 40 ]
=> 条件 > 20
=> 结果 [ 30, 40 ]filter + 语法: 数组.filter(function (item, index, arr) {}) + 返回值: 一个新的数组 => 原始数组中满足条件的项 => 在回调函数中以 return 的形式书写 过滤条件
*/
// 1. 准备方法
// Array.prototype.myFilter = function (cb) {
// // 1-1. 准备一个新的数组
// var ary = []// // 1-2. 根据 回调函数 的条件, 向 新数组内 添加成员
// for (var i = 0; i < this.length; i++) {
// // 需要调用 cb
// var r = cb(this[i], i, this)// // ary.push(this内满足条件的项)
// r && ary.push(this[i])
// }// // 1-3. 返回新数组
// return ary
// }// // 2. 将来使用的时候
// var arr = [ 10, 20, 30, 40 ]
// var res = arr.filter(function (item, index, arr) {
// // 过滤条件
// return item > 20
// })// console.log('原始数组 : ', arr)
// console.log('过滤以后 : ', res)
数组常用办法every和some
-
/*
数组常用方法 - every 和 someevery + 判断数组内是不是所有项都满足条件 + 如果所有项都满足条件, 那么返回值是 true + 只要有任意一项不满足条件, 那么返回值是 false some + 判断数组内是不是有某一项满足条件 + 只要数组内任意一项满足条件, 那么返回值就是 true + 只有所有项都不满足条件的时候, 返回值才是 false
*/
// // 1. 准备方法
// Array.prototype.myEvery = function (cb) {
// // 1-1. 提前假设一个变量, 假设所有都满足条件
// var flag = true// // 1-2. 循环遍历数组来验证我的假设
// for (var i = 0; i < this.length; i++) {
// var r = cb(this[i], i, this)// // 如果在循环过程中, r 为 false 了, 说明当前这一个不是满足条件的项
// // 推翻我的假设
// if (!r) {
// flag = false
// break
// }
//
// }// // 1-3. 返回我的 flag
// return flag
// }// // 2. 将来使用的时候
// var arr = [ 10, 20, 30, 40, 50 ]
// var res = arr.myEvery(function (item, index, arr) {
// console.log(item)
// return item > 10
// })
// console.log(res)// 1. 准备方法
Array.prototype.mySome = function (cb) {
// 1-1. 提前假设一个变量, 假设完全没有
var flag = false// 1-2. 循环遍历数组来验证我的假设 for (var i = 0; i < this.length; i++) { var r = cb(this[i], i, this) if (r) { flag = true break } } // 1-3. 返回我的 flag return flag
}
// 2. 将来使用的时候
var arr = [ 10, 20, 30, 40, 50 ]
var res = arr.some(function (item, index, arr) {
console.log(item)
return item > 10
})
console.log(res)
数组常用办法三
-
/*
数组常用方法3
1. flat()
=> 语法: 数组.flat(数字)
-> 如果不传递参数, 默认拍平一层
-> 传递的数字是几, 就拍平多少层
-> 不管多少维度都直接拍平, Infinity
=> 作用: 拍平一个数组(把多维转换成一维)2. find() => 语法: 数组.find(function (item, index, arr) {}) => 返回值: 数组中满足条件的第一个 -> 以 return 的形式书写条件 3. findIndex() => 语法: 数组.findIndex(function (item, index, arr) {}) => 返回值: 数组中满足条件的第一个的索引位置 -> 以 return 的形式书写条件 4. includes() => 语法: 数组.includes(数据) => 返回值: 一个布尔值 -> 如果数组内有改数据, 那么就是 true -> 如果数组内没有该数据, 那么就是 false 5. fill() => 语法: 数组.fill(要填充的数据, 开始索引, 结束索引) -> 开始索引不写默认是 0 -> 结束索引不写, 默认是最后一位的索引 -> 特点: 索引 包前不包后(包含开始索引, 不包含结束索引) => 作用: 替换, 按照索引位置替换数组内指定索引的数据 -> 等价于 arr[2] = '你好 世界' => 注意: 直接改变原始数组 => 注意: 只能替换现有数据, 不能新增 6. reduce() => 语法: 数组.reduce(function (prev, item, index, arr) {}, init) -> init 如果不写, 默认使用数组中的第一个数据 => 作用: 叠加 => 返回值: 就是叠加后的结果 */ // 1. flat // var arr = [10, [20, 30, [40, 50, [60, 70, [80, [90]]]]]] // var res = arr.flat(Infinity) // console.log(arr) // console.log(res) // 2. find() // var arr = [ 10, 20, 30, 40, 50, 60 ] // var res = arr.find(function (item) { // return item % 3 === 0 // }) // console.log(res) // 3. findIndex() // var arr = [ 10, 20, 30, 40, 50, 60 ] // var res = arr.findIndex(function (item) { // return item % 3 === 0 // }) // console.log(res) // 4. includes() // var arr = [ 10, 20, 30, 40, 50, 60 ] // var res = arr.includes(33) // console.log(res) // 5. fill() // var arr = [ 10, 20, 30, 40, 50, 60 ] // console.log('原始数组 : ', arr) // arr.fill('新来的') // 从 [2] 开始到 [5] 结束, 包含 [2] 不包含 [5] // arr.fill('新来的', 2, 5) // arr.fill('新来的', 2) // arr.fill('新来的', 2, 100) // console.log('原始数组 : ', arr) // 6. reduce() var arr = [ 10, 20, 30, 40, 50, 60 ] var res = arr.reduce(function (prev, item) { console.log(prev, item) return prev + item }, 100) console.log('最终结果: ', res) /* 你设置了 init 位置参数 循环第一次, prev 就是 init 位置的值, item 就是数组内的第一项 循环第二次, prev 就是上一次 return 的内容, item 是数组当前第二项 你没有设置 init 位置参数 此时, 会默认使用数组中的 [0] 这一项当做 init 位置参数 循环第一次, prev 就是数组 [0] 的值, item 就是索引当前项 [1] 如果没有 init 位置的数据, 那么数组从 [1] 开始遍历 */
数组常用办法四
-
数组常用方法4
1. concat() + 拼接数组 + 语法: 数组.concat(数组2, 数据, 数组3) + 作用: 把所有参数内的数组或者数据追加到原始数组的最后面, 如果参数是数组, 那么拆开追加 + 返回值: 拼接好的数组 + 注意: 不会改变原始数组 2. join() + 连接数组 + 语法: 数组.join(连接符号) => 连接符号如果不写, 默认使用 ',' + 作用: 把数组内每一项使用连接符号连接为一个字符串 + 返回值: 是一个字符串类型 + 注意: 不会改变原始数组 3. slice() + 截取数组 + 语法: 数组.slice(开始索引, 结束索引) => 特点: 包前不包后 => 特点2: 可以写负整数, 就是倒数第几个. 等价于 length + 负整数 => 开始索引不填写, 默认是 0 => 结束索引不填写, 默认是 length + 返回值: 一个新的数组 => 里面存放的就是你截取出来的内容 + 注意: 不会改变原始数组 4. indexOf() + 语法: => 数组.indexOf(要查找的数据) => 数组.indexOf(要查找的数据, 开始索引) + 返回值: => 从前向后检索, 检索第一个满足要求的数据 => 返回第一个满足要求的数据的索引位置 => 如果有这个数据, 返回索引位置 => 如果没有这个数据, 返回 -1 5. lastIndexOf() + 语法: => 数组.lastIndexOf(要查找的数据) => 数组.lastIndexOf(要查找的数据, 开始索引) + 返回值: => 从后向前检索, 检索第一个满足要求的数据 => 返回第一个满足要求的数据的索引位置 => 如果有这个数据, 返回索引位置 => 如果没有这个数据, 返回 -1
*/
// 1. concat()
// var arr = [ 10, 20, 30 ]
// console.log(arr)
// var a2 = [ 40, 50, 60 ]
// var a3 = [ 70, 80, 90 ]
// var res = arr.concat(a2, a3)
// console.log(arr)
// console.log(res)// 2. join()
// var arr = [ 2022, 2, 28 ]
// console.log(arr)
// var res = arr.join(’_’)
// console.log(arr)
// console.log(res)
// console.log(typeof res)// 3. slice()
// var arr = [ 10, 20, 30, 40, 50, 60, [70] ]
// // 0 1 2 3 4 5
// console.log('原始数组 : ', arr)
// // 从 [2] 截取到 [5], 包含 [2] 不包含 [5]
// // var res = arr.slice(2, 5)
// // 从 [1] 截取到 [-1], 这里的 [-1] 等价于 arr.length + -1
// // var res = arr.slice(1, -1)
// var res = arr.slice()
// console.log(arr)
// console.log('返回值 : ', res)// arr[2] = ‘修改一下’
// console.log(arr)
// console.log(res)// 4. indexOf()
// var arr = [ 10, 20, 30, 20, 10, 20, 30 ]
// console.log('原始数组 : ', arr)
// // var res = arr.indexOf(20)
// // 从 [2] 位置开始向后检索
// var res = arr.indexOf(20, 2)
// console.log(res)// 5. lastIndexOf()
// var arr = [ 10, 20, 30, 20, 10, 20, 30 ]
// console.log(arr)
// var res = arr.lastIndexOf(20)
// 从 [4] 位置开始向前查找
// var res = arr.lastIndexOf(20, 4)
// console.log(res)
数组常用办法总结
-
/*
数组常用方法 - 总结1. push() => 后面追加 => 返回值: 追加后数组最新的长度 2. pop() => 后面删除 => 返回值: 被删除的数据 3. unshift() => 前面添加 => 返回值: 添加后数组最新的长度 4. shift() => 前面删除 => 返回值: 被删除的数据 5. reverse() => 数组反转 => 返回值: 反转后的数组 6. sort() => 数组.sort() ASCII => 数组.sort(function (a, b) { return a - b }) 升序 => 数组.sort(function (a, b) { return b - a }) 降序 => 数组排序 => 返回值: 排序后的数组 7. splice() => 数组.splice(开始索引, 多少个) => 数组.splice(开始索引, 多少个, 插入数据) => 数组截取并选择性的插入数据, 注意: 从哪里删除, 从哪里插入 => 返回值: 一个新的数组, 存储的是截取出来的所有内容 ===================== 以上数组常用方法, 都是直接改变原始数组 ===================== 8. concat() => 拼接数组 => 返回值: 拼接好的新数组 9. join(连接符) => 使用连接符连接数组内的每一项 => 返回值: 一个字符串类型, 使用连接符连接好的内容 10. slice() => 数组.slice(开始索引, 结束索引) -> 特点1: 包前不包后 -> 特点2: 可以填写负整数 => 截取数组内的内容 => 返回值: 一个新的数组, 数组内存储的是截取出来的内容 11. indexOf() => 从前向后检索数据出现的索引位置 => 返回值: 如果有这个数据, 就是第一次出现的索引位置, 如果没有这个数据, 就是 -1 12. lastIndexOf() => 从后向前检索数据出现的索引位置 => 返回值: 如果有这个数据, 就是第一次出现的索引位置, 如果没有这个数据, 就是 -1 13. forEach(function (item, index, arr) {}) => 遍历数组 => 返回值: 没有 14. map(function (item, index, arr) {}) => 映射数组 => 返回值: 一个新的数组, 对原始数组内每一项操作后的结果 15. filter(function (item, index, arr) {}) => 过滤数组 => 返回值: 一个新的数组, 原始数组内满足条件的新数组 16. every(function (item, index, arr) {}) => 判断是否每一项都满足条件 => 返回值: -> 如果数组内每一项都满足条件, 那么返回 true -> 只要有任何一项不满足条件, 那么返回 false 17. some(function (item, index, arr) {}) => 判断是否某一项满足条件 => 返回值: -> 如果数组内有任何一项满足条件, 那么返回 true -> 只有数组内所有都不满足条件, 那么返回 false 18. find(function (item, index, arr) {}) => 根据条件查找数组中的数据 => 返回值: 查找到的数据 19. findIndex(function (item, index, arr) {}) => 根据条件查找数组中的数据所在的索引位置 => 返回值: 查找到的数据的索引位置 20. flat(数字) => 拍平数组 => 数组: 书写多少, 就是拍平多少层 -> 可以书写 Infinity 来表示全部拍平 => 返回值: 一个被拍平的数组 21. fill() => 填充数组 => 数组.fill(填充数据, 开始索引, 结束索引) -> 特点: 包前不包后 => 注意: 会直接改变原始数组 => 注意: 只能填充现有索引位置数据, 不能新增数据 22. includes() => 判断是否存在数据 => 返回值: 一个布尔值 -> 如果数组内有该数据, 那么返回 true -> 如果数组内没有该数据, 那么返回 false 23. reduce(function (prev, item, index, arr), init) => init 可以写可以不写, 不写的时候默认使用数组 [0] 位置的数据 => 当 init 不写的时候, 遍历会从 [1] 开始 => 当 init 书写的时候, 遍历会从 [0] 开始 => 叠加数组 => 返回值: 最终的叠加结果
*/
数组去重
- /*
数组去重 - if
*/
var arr = [ 10, 20, 30, 40, 10, 20, 30, 10, 20, 30, 10 ]
console.log('原始数组 : ', arr)
// 1. 遍历数组
for (var i = 0; i < arr.length; i++) {
// i 表示当前这一项的索引
// 从 i + 1 开始查找, 找找看后面还有没有这个数据
var r = arr.indexOf( arr[i], i + 1 )
// 没有学习 indexOf 之前, 在这里书写一个 循环, 找到 索引位置
// 判断是否存在
if (r !== -1) {
arr.splice(r, 1)
i--
}
}
console.log('去重之后 : ', arr)
作业
-
/*
按照顺序向数组内插入一个数据
*/// 已知排序完整的数组
var arr = [ 10, 20, 30, 40, 50 ]// 准备要插入的数字
var n = 22// code run here …
// 结果: 把 n 按照现有顺序插入到数组内
/*
预习:
=> 快速排序
=> 插入排序
*/