JS函数——高阶函数、函数柯里化、防抖和节流

本文深入探讨JavaScript中的高阶函数,包括forEach、Map、reduce、filter等常见应用及自定义实现。接着介绍函数柯里化的概念、意义及实现方式。最后,详细阐述防抖和节流的原理、应用场景及区别,帮助前端开发者提升性能优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

随着前端学习的深入,高阶函数、函数柯里化、防抖和节流的概念及实现成为了我们需要掌握和了解的内容。


一、高阶函数

1. 什么是高阶函数?

	如果一个函数接受另一个函数作为参数,那么我们就将该函数称为高阶函数。

2. JavaScript中常见的高阶函数

1. forEach和Map


var arr = [1, 2, 3];
arr.forEach((item, index) => {
	console.log(item, index);
})
//手写forEach方法
Array.prototype.myForEach = function (callback) {
	var len = this.length;
	if(typeof callback !== "function") {
		throw new Error("muse be function");
	}
	for(var i = 0; i < len; i++) {
		callback.call(this, this[i], i);	//this[i] 当前项,i 下标。
	}
}

var arr1 = arr.map((item, index) => {
	if(item === 1) {
		item += 2;
	}
	return item;
})
//手写map方法
Array.prototype.myMap = function (callback) {
	var len = this.length;
	var arr = [];
	if(typeof callback !== "function") {
		throw new Error("muse be function");
	}
	for(var i = 0; i < len; i++) {
		arr.push(callback.call(this, this[i], i));
	}
	return arr;
}

2. reduce


var arr = [1, 2, 3];
var sum = arr.reduce((pre, now, index, arr) => {	//pre是上一轮循环返回的值(或初始值);now当前项;index前项下标;arr当前项所属的数组;
	return pre + now;
}, 0)	//0是初始值,也就是第一轮循环时pre的值,当没有设置初始值时,整体减少一轮循环,第一轮循环pre值为数组的第一项。

//手写reduce方法
Array.prototype.myReduce = function (fn, initvalue) {
	val i = 0;
	var len = this.length;
	var pre = initvalue;
	if(initvalue == undefined) {	//如果没有传入初始值,第一轮循环pre值取数组的第一项,循环从下标为1的项开始。
		pre = this[0];
		i = 1;
	}
	for(i; i < len; i++) {
		pre = fn.call(this, pre, this[i], i, this);
	}
	return pre;
}

3.filter


var arr = [1, 2, 3, 4, 5, 6, 7];
var arr1 = arr.filter((item, index) => {
	return item % 2 === 0;
})

//手写filter方法
Array.prototype.myFilter = function (callback) {
	var _newArray = [];
	var len = this.length;
	for(var i = 0; i < len; i++) {
		if(callback.call(this, this[i], i)) {
			if(typeof this[i] === "object") {	//如果当前项是一个对象,我们需要先将其克隆,再加入到_newArray中。
				_newArray.push(Object.create(this[i]));
			}
			_newArray.push(this[i]);
		}
	}
	return _newArray;
}

4.编写自定义高阶函数

编写自定义高阶函数需要注意的点:
	1. 保持纯函数和减少函数副作用;
	2. 调用选择call还是apply;

//找出对象中符合要求的属性名
var obj = {
	num1: 1,
	num2: 2,
	num3: 3,
	num4: 4,
	num5: 5,
	num6: 6
}
function findProperty (obj, fn) {
	var _obj = Object.create(obj);
	var _propertyArray = [];
	for(var item in _obj) {
		if(fn.call(_obj, _obj[item], item)) {
			_propertyArray.push(item);
		}
	}
	return _propertyArray;
}
findProperty(obj, (val, key) => {
	return value % 2 == 0;
})

二、函数柯里化

1.什么是函数柯里化?

	函数柯里化就是把接收多个参数的函数,变换成接收一个单一参数(最初函数的第一个参数)的函数,这个函数接收余下的参数,并且返回结果。

2.柯里化的意义

2.1. 遇到不方便传入参数时


//回调
function a(val) {
	console.log(val);
}
//当我们需要在Promise中的then方法中执行a方法,此时我们会发现val是a方法必传的参数,如果直接传val调用a方法的话,then方法中就不是执行的就不是一个函数了。
Promise.resolve().then(a.bind(this, 123));	//bind方法返回一个新的函数

2.2. 当写了一个方法,但是这个方法很多时候调用起来参数是固定的时候


//有个表单需要验证输入的值符不符合规定
function inputTest(reg, val) {
	return reg.test(val);
}
//有个表单中有10个input框需要验证输入的是不是纯数字的
const numberTest = inputTest.bind(this, /^[0-9]*$/);
numberTest(val);

3.如何实现柯里化?

	柯里化函数会接收到固定参数,然后在柯里化函数里面,返回一个新的函数,接收剩余参数。
//最简单的柯里化
function a(num1, num2) {
	console.log(num1, num2);
}
function aCurry(num1) {
	return function(num2){
		console.log(num1, num2);
	}
}
aCurry(1)(2);

//手写一个bind方法
Function.prototype.myBind = function (thisArg) {	//第一项肯定是规定调用myBind方法的函数,其指向
	if(typeof this !== "function"){	//这里的this谁调用的myBind方法就指向谁
		throw new Error("muse be function");
	}
	var _self = this;
	var args = Array.prototype.slice.call(arguments, 1);
	return function () {
		return _self.apply(thisArg, args.concat(Array.prototype.slice.call(arguments)));	//concat方法用于连接两个或多个数组,并返回一个新数组
	}
}

三、防抖和节流

1.防抖

	防抖就是将某些高频触发的操作,变成只操作一次(也就是等用户高频事件完了,在进行事件操作)。

1.1. 为什么要做防抖?

	当我们监听input框输入事件时,我们不需要客户每输入一个字母就触发一次监听,应该是客户完成一段输入后,再触发监听。

1.2. 防抖怎么做?

在这里插入图片描述


//手写一个防抖方法
function antiShake(fn, delay) {
	vat timer = null;
	return function () {
		clearTimeout(timer);
		timer = setTimeout(() => {
			fn.apply(this, arguments);
		}, delay)
	}
}

2.节流

	节流是指某个操作希望上一次事件完成后,再进行下一次(或者希望隔一定时间触发一次)。

2.1. 为什么要做节流?

	如果我们写个加入购物车按钮,点击后按钮后,向服务器发送一个添加商品到购物车的请求。
	这里如果我们采用防抖方法,如果我们一直点,那么就不会向后端发送请求。
	采用节流,如果我们一直点,会第一次点击发送请求出去,然后等到请求返回后,再发送下一个请求。

2.2. 节流怎么做?

在这里插入图片描述


//手写一个节流方法
function throttle(fn, delay) {
	var _switch = true;
	if(_switch) {
		setTimeout(() => {
			fn.apply(this, argments);
			_switch = true;
		}, delay)
		_switch = false;
	}else {
		return false;
	}
}

3. 防抖和节流的相同点

	防抖和节流都是为了阻止操作高频触发,从而影响性能。

4. 防抖和节流的区别

	1. 防抖是使操作多次触发,只生效最后一次。适用于只需要一次触发生效的场景。
	2. 节流是使操作每隔一段时间才能触发一次。适用于需要多次触发多次生效的场景。

总结

革命尚未成功,同志仍需努力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值