JavaScrip之函数柯理化、参数复用、提前确认、延迟执行

2023-12-04 22:44

本文主要是介绍JavaScrip之函数柯理化、参数复用、提前确认、延迟执行,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MENU

  • 1、参数复用
  • 2、提前确认 (惰性函数)
  • 3、延迟运行
  • 4、初步封装
  • 5、递归封装
  • 6、经典面试题


1、参数复用

// 普通函数验证
function check(regExp, text) {return regExp.test(text);
}console.log(check(/^\d+$/g, '123')); 
// true
console.log(check(/^\d+$/g, '2d')); 
// falseconsole.log(check(/^[a-z]+$/g, 'text')); 
// true
console.log(check(/^[a-z]+$/g, '3d')); 
// false// --------------------------------------------------------------------------// Currying后
function curryingCheck(regExp) {return function(regExp) {return reg.test(regExp);}
}let hasNumber = curryingCheck(/^\d+$/g);
let hasLetter = curryingCheck(/^[a-z]+$/g);console.log(hasNumber('159')); 
// true
console.log(hasNumber('2d')); 
// falseconsole.log(hasLetter('3d')); 
// false
console.log(hasLetter('text')); 
// true

示例是一个正则的校验,正常来说直接调用check函数就可以,但是如果有很多地方都要校验是否有数字,其实就是需要将第一个参数reg进行复用,这样别的地方就能够直接调用hasNumber,hasLetter等函数,让参数能够复用,调用起来也更方便。


2、提前确认 (惰性函数)

// 方案一
let on = function(element, event, handler) {if (document.addEventListener) {if (element && event && handler) {element.addEventListener(event, handler, false);};} else {if (element && event && handler) {element.attachEvent('on' + event, handler);};};
};// 方案二
// ()(); => ~function() {.. ..}();
let on = (function() {if (document.addEventListener) {return function(element, event, handler) {if (element && event && handler) {element.addEventListener(event, handler, false);};};} else {return function(element, event, handler) {if (element && event && handler) {element.attachEvent('on' + event, handler);};};};
})();// 方案三
// 换一种写法可能比较好理解一点,
// 上面就是把isSupport这个参数给先确定下来了
let on = function(isSupport, element, event, handler) {isSupport = isSupport || document.addEventListener;if (isSupport) {return element.addEventListener(event, handler, false);} else {return element.attachEvent('on' + event, handler);};
};

在做项目的过程中,封装一些dom操作可以说再常见不过,上面第一种写法也是比较常见,但是看看第二种写法,它相对于第一种写法就是自执行然后返回一个新的函数,这样其实就是提前确定了会走哪一个方法,避免每次都进行判断。


3、延迟运行

Function.prototype.bind = function (context) {let that = this,args = Array.prototype.slice.call(arguments, 1);return function() {return that.apply(context, args);};
};

js中经常使用的bind,实现的机制就是Currying。


4、初步封装

let currying = function(fn) {// args获取第一个方法内的全部参数let args = Array.prototype.slice.call(arguments, 1);return function() {// 将后面方法里的全部参数和args进行合并var newArgs = args.concat(Array.prototype.slice.call(arguments));// 把合并后的参数通过apply作为fn的参数并执行return fn.apply(this, newArgs);};
};

通过闭包把初步参数给保存下来,然后通过获取剩下的arguments进行拼接,最后执行需要currying的函数。但是,有缺陷,这样返回的只能多扩展一个参数,currying(a)(b);这样的话,就不支持多参数调用。


5、递归封装

// 支持多参数传递
function progressCurrying(fn, args) {let that = this;let len = fn.length;let args = args || [];return function() {let _args = Array.prototype.slice.call(arguments);Array.prototype.push.apply(args, _args);// 如果参数个数小于最初的fn.length,则递归调用,继续收集参数if (_args.length < len) {return progressCurrying.call(that, fn, _args);}// 参数收集完毕,则执行fnreturn fn.apply(this, _args);};
}

其实是在初步的基础上,加上了递归的调用,只要参数个数小于最初的fn.length,就会继续执行递归。


6、经典面试题

实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;


function add() {// 第一次执行时,定义一个数组专门用来存储所有的参数let _args = Array.prototype.slice.call(arguments);// 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值let _adder = function() {_args.push(...arguments);return _adder;};// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回_adder.toString = function () {return _args.reduce(function (a, b) {return a + b;});};return _adder;
}console.log(add(1)(2)(3)); // 6
console.log(add(1, 2, 3)(4)); // 10
console.log(add(1)(2)(3)(4)(5)); // 15
console.log(add(2, 6)(1)); // 9

这篇关于JavaScrip之函数柯理化、参数复用、提前确认、延迟执行的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/455171

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>