1.高阶函数:就是一个函数的参数是函数,或者返回值是函数,满足其中一个就是高阶函数。
开闭原则:对扩展是开发的,对修改是封闭的。
//定义一个计算器函数
// 注意:callback参数,接收的是一个函数。
function calc(num1,num2,callback){
return callback(num1,num2)
}
//简写
//let calc=(num1,num2,callback)=>callback(num1,num2);
// 定义一个加法运算
let add = function(num1,num2){
return num1 + num2
}
// 计算两个数,统一调用calc方法,具体是如何计算,通过回调函数去实现。
//先定义一个回调函数,在传进来
let r1 = calc(300,100,add)
console.log(r1);
//回调函数可以直接调用时定义
let r2 = calc(300,100,function(num1,num2){return num1 - num2})
console.log(r2);
//通常情况下,回调函数都会写成箭头函数的形式
let r3 = calc(300,100, (num1,num2)=>num1 * num2)
console.log(r3);
let r4 = calc(300,100,(num1,num2)=>num1/num2)
console.log(r4);
let r5 = calc(16,6,(num1,num2)=>num1%num2)
console.log(r5);
2.回调函数练习
let arr = [11, 22, 33, 44, 55, 66, 77, 88, 99, 111, 222, 333, 444]
//定义一个kaiFor函数,这个函数需要传两个参数:数组,回调函数
function kaifor(arr, callback) {
//循环数组
for (let i = 0; i < arr.length; i++) {
//调用回调函数callback,将数组中的每个数传进去,返回true,表示满足条件
if (callback(arr[i])) {
console.log(arr[i]);
}
}
}
// 业务一:循环输出数组中所有的奇数
// 定义一个函数,用于返回一个数是不是奇数
function isJs(num){
return num%2!==0
}
kaifor(arr,isJs)
console.log('--------------------');
// 业务二:循环输出数组中所有的偶数
kaifor(arr,function(num){return num%2===0})
console.log('--------------------');
// 业务三:循环输出数组中所有的能被3整除的数
kaifor(arr,num => num%3===0)
console.log('--------------------');
// 业务四:循环输出数组中所有的3位数
kaifor(arr,num => num>=100 && num<1000)
3.数组的高阶方法
let arr = [11, 22, 33, 44, 55, 66, 77, 88, 99, 111, 222, 333, 444]
1.forEach()方法,用于循环遍历整个数组
//该方法的参数是一个回调函数,回调函数可传两个参数,第一个参数是数组中的每一项元素
//第二个参数是每一项元素对应的下标。
//注意:第二个参数可以省略。
arr.forEach((val,index)=>console.log(index+'-'+val))
2.filter()方法,用于过滤数组中的元素,返回过滤结果
let arr1 = arr.filter(val=>val%2==0)
console.log(arr1);
let arr2 = arr.filter(val=>val%3==0)
console.log(arr2);
3.find()方法,用于获取数组中满足规则的第一个元素
let num1 = arr.find(val=>val%3==0)
console.log(num1);
4.findIndex()方法,用于获取数组中满足规则的第一个元素下标
let index1 = arr.findIndex(val=>val%3==0)
console.log(index1);
5.some()方法,用于表示数组中是否有满足指定规则的元素,有返回true,一个都没有返回false
let isHave1 = arr.some(val=>val>1000)
console.log(isHave1);
let isHave2 = arr.some(val=>val==222)
console.log(isHave2);
6.every()方法,用于表示数组中是否所有元素都满足指定的规则
let isHave3 = arr.every(val=>val>10)
console.log(isHave3);
let isHave4 = arr.every(val=>val%2==0)
console.log(isHave4);
7.map()方法,用于将原始数组里面的数据根据指定的规则返回新的数组
let arr3 = arr.map(r=>r%7)
console.log(arr3);
console.log('------------------------------');
let arr4 = [33,22,55,7,46]
8.sort()方法,对数组的元素进行排序
回调函数需要传两个参数,返回参数1-参数2是升序,返回参数2-参数1是降序
console.log(arr4);
arr4.sort((a,b)=>a-b)
console.log(arr4);
arr4.sort((a,b)=>b-a)
console.log(arr4);
9.reduce()方法,统计数组中元素的和(从左到右)
a是数组中的一个数,b从数组中第二个数开始,回调函数的返回是a的下一次的值
let sum1 = arr4.reduce((a,b)=>{
return a+b
})
console.log(sum1);
console.log('-------------------------------');
// reduce()方法,可以给a设置一个起始值,这里的100就是a的起始值,b从数组的第一位 (下标是0)开始
let sum2 = arr4.reduce((a,b)=>{
return a+b
},100)
console.log(sum2);
10.reduceRight()方法,统计数组中元素的值(从右到左)
let sum3 = arr4.reduceRight((a,b)=>{
return a+b
})
console.log(sum3);
4.手写实现数组的高阶方法
let arrs = [11, 22, 33, 44, 55]
1.手写forEach()方法
function forEach(arr, callback) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i)
}
}
forEach(arrs, (item, index) => console.log(index + '---' + item))
console.log('----------------------------');
2.手写filter()方法
function filter(arr, callback) {
let val = [];
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
val.push(arr[i]);
}
}
return val;
}
console.log(filter(arrs, num => num % 2 == 0));
console.log(filter(arrs, num => num > 30));
console.log('----------------------------');
3.手写find()方法
function find(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
return arr[i];
}
}
}
console.log(find(arrs, num => num % 2 == 0));
console.log(find(arrs, num => num > 30));
console.log('----------------------------');
4.手写findIndex()方法
function findIndex(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
return i;
}
}
}
console.log(findIndex(arrs, num => num % 2 == 0));
console.log(findIndex(arrs, num => num > 30));
console.log('----------------------------');
5.手写some()方法
function some(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
return true;
}
}
return false;
}
console.log(some(arrs, num => num % 2 == 0));
console.log(some(arrs, num => num > 100));
console.log('---------------------------');
6.手写every()方法
function every(arr, callback) {
for (let i = 0; i < arr.length; i++) {
if (!callback(arr[i])) {
return false;
}
}
return true;
}
console.log(every(arrs, num => num > 10));
console.log(every(arrs, num => num % 3 == 0));
console.log('---------------------------');
7.手写map()方法
function map(arr, callback) {
let val = [];
for (let i = 0; i < arr.length; i++) {
val.push(callback(arr[i]));
}
return val;
}
console.log(map(arrs, num => num % 3));
console.log(map(arrs, num => num / 2));
console.log('----------------------------');
8.手写sort()方法
function sort(arr, callback) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (callback(arr[i], arr[j]) > 0) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp;
}
}
}
return arr;
}
console.log(sort(arrs, (a, b) => a - b)); //升序
console.log(sort(arrs, (a, b) => b - a)); //降序
console.log('----------------------------');
9.手写reduce()方法
function reduce(arr, callback, initNum) {
for (let i = 0; i < arr.length; i++) {
let r = callback(initNum, arr[i])
initNum = r //每次返回的结果,需要替换initNum
}
return initNum;
}
console.log(reduce(arrs, (a, b) => a + b, 0));
console.log('----------------------------');
10.手写reduceRight()方法
function reduceRight(arr, callback, initNum) {
for (let i = arr.length - 1; i >= 0; i--) {
let r = callback(initNum, arr[i])
initNum = r //每次返回的结果,需要替换initNum
}
return initNum
}
console.log(reduceRight(arrs, (a, b) => a + b, 0));
5.闭包函数
function a(){
console.log('a函数被调用了...');
let num1 = 100
let num2 = 200
function b(){
console.log('b函数被调用了...');
console.log(num1 + num2);
}
//返回的返回值也是一个函数,那么a函数,就是高阶函数。
return b
}
// 通常情况下,函数执行完成后,函数里面定义的变量,会被销毁。
// a函数,已经调用完毕了,但是a函数里面定义变量,始终在内存中,因为b函数中用到了a函数中定义的变量。
// 那么此时这两个函数,就称之为:闭包函数。
let c = a()
c()
console.log('------------------------------------------');
// 闭包函数的实际案例
function calc(num1,num2,type){
switch(type){
case '+':
console.lo2g(`${num1}+${num72}=${num1+num2}`);
break;
case '-':
console.log(`${num1}-${num2}=${num1-num2}`);
break;
}
}
// 在实际开发中,我们在做num1和num2的计算之前,可能需要先做其他事情
let num1 = 100
let num2 = 50
// 在做其他事情的过程中,我们的数据很有可能会被篡改。
console.log('查看用户是否登录');
num1 = 555
num2 = 145
console.log('检查用户的权限');
calc(num1,num2,'+') //运行结果不对,因为变量的值被篡改了。
console.log('------------------------------------------');
// 定义一个闭包函数,实现计算器功能
function myCalc(num1,num2,type){
switch(type){
case '+':
return function(){
return num1 + num2
}
case '-':
return function(){
return num1 - num2
}
}
}
//先准备好你的数据
let n1 = 100
let n2 = 50
//将你的数据传给计算器方法,由计算器方法,返回一个计算方法。
let js = myCalc(n1,n2,'+')
//在做具体的计算之前,还先做些其他的事情
console.log('查看用户是否登录');
n1 = 555
n2 = 145
console.log('检查用户的权限');
//其他事件准备好了后,执行计算方法
console.log(js());
6.arguments
function fn1(a,b,c){
//方法在调用时,如果没有传递实参,形参的值是undefined
console.log(a,b,c);
// arguments是函数内部的一个内置对象
// arguments对象里面保存这方法的所有参数
// arguments对象里面有个一个callee方法,该方法指向当前方法本身
console.log(arguments);
let sum = 0;
for(let i=0;i<arguments.length;i++){
sum+=arguments[i]
}
return sum;
}
let sum = fn1(100,200,300,400,500,600)
console.log(sum);
// 计算1-20之间所有数的求和
function calc(num){
if(num===1){
return num
}
// arguments.callee指向当前方法本身。
// 所以,在写递归算法时会经常使用。
return num + arguments.callee(num-1)
}
console.log(calc(20));
7.分页方法
// 定义一个数组
let arr = [11,22,33,44,55,66,77,88,99,111,222,333,444,555,666,777,888,999]
// 每页3条数据,返回第3页数据
let r1 = arr.slice(6,9)
console.log(r1);
// 每页4条数据,返回第4页数据
let r2 = arr.slice(12,16)
console.log(r2);
// 没有5条数据,返回第3页数据
let r3 = arr.slice(10,15)
console.log(r3);
console.log('------------------------------');
//定义一个分页方法,方法的三个参数分别是:原始数组,页码,每页数量
function pageDate(arr,pageIndex,pageSize){
let start = (pageIndex-1)*pageSize
let end = start+pageSize
//根据起始下标和结束下标,从原始数组中截取对应的数据并返回
return arr.slice(start,end)
}
console.log(pageDate(arr,3,3));
console.log(pageDate(arr,4,4));
console.log(pageDate(arr,3,5));