初涉JavaScript模式 (9) : 函数 【常用方式】

2023-11-21 19:20

本文主要是介绍初涉JavaScript模式 (9) : 函数 【常用方式】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

回调模式

上一篇,对JavaScript函数进行了大体的介绍,这一篇对一些在工作中经常遇到的情况进行扩展。

在工作中,我们经常遇到很多需求,比如现在有一个需求:

一栋10层的大楼,当我们在坐电梯时,电梯每上一层,每层的电梯显示屏上即时显示电梯当前所在的楼层。

这样我们可能不到1s,就想到了解决方案,只要电梯每上一层,把每一层的电梯显示屏数字 +1 ,代码核心如下:

```javascriptfunction processArrayA(nums, scalar) {var arr = [];nums.forEach(function(value) {arr.push(value + scalar);});return arr;}var numsA = [1, 2, 3, 4, 5];console.log(processArrayA(numsA, 1)); //[2,3,4,5,6]
```

每当电梯升一层,我们只要调用processArrayA()方法就可以完成需求,但是假如后续又加了需求(PM一般都这样,呵呵),希望我们在电梯下降的时候也 -1,这样也没事,我们马上写出了代码:

```javascriptfunction processArrayB(nums, scalar) {var arr = [];nums.forEach(function(value) {arr.push(value - scalar);});return arr;}var numsA = [1, 2, 3, 4, 5];console.log(processArrayB(numsA, 1)); //[0,1,2,3,4]
```

额,当我们迅速解决了需求后,该死的PM又来了(悲催),说这栋楼希望显示2倍层数(奇葩有木有。。),作为技术的我们还得做。。。额,于是我们又给出了代码:

```javascriptfunction processArrayC(nums, scalar) {var arr = [];nums.forEach(function(value) {arr.push(value * scalar);});return arr;}var numsA = [1, 2, 3, 4, 5];console.log(processArrayC(numsA, 2)); //[2,4,6,8,10]
```

额,到这时候,我们也知道PM的需求是无止境的(谁知道脑残的PM再能想出什么奇葩来),而作为工程师的我们也开始再思考如何能一劳永逸了(懒程序才是好程序),额,这时我们的回调模式就派上用场了,我们发现前面三段代码示例除了forEach里面的逻辑有变化,其他都是没有变化的,我们要是把这段代码逻辑隔离出来,不就OK了。代码如下:

```javascript//回调模式function processArrayB(nums, scalar, callback) {var arr = [];nums.forEach(function(value) {arr.push(callback(value, scalar));});return arr;}function add(value, scalar) {return value + scalar;}function subtract(value, scalar) {return value - scalar;}function ride(value,scalar){return value * scalar;}var numsB = [1, 2, 3, 4, 5];console.log(processArrayB(numsB, 2, add)); //[3,4,5,6,7]console.log(processArrayB(numsB, 5, subtract));//[-4,-3,-2,-1,0]console.log(processArrayB(numsB, 2, ride));//[2,4,6,8,10]
```

这样我们顺利的把add,ride。。方法独立出来,作为callback的形式,让处理函数去调用,而每次增加需求,我们只需要简单的添加callback函数就OK了(简单情况下),相比这个简单的需求,有时候我们可能会遇到复杂N倍的代码逻辑,而这时候回调模式就显得格外重要。

回调模式的用法很常见,比如我们addEventListener的时候里面的callback,而在一些常见的库中就应用的更加广泛了,例如Jq的“钩子” ,这样的好处就是我们在coding的过程中,只需要关注核心代码的实现,而不必考虑到每一种业务逻辑(可以通过callback的方式),这样会让我们更方便的扩展,构建,自定义自己的组件。

暴露接口

在JavaScript中,我们花了很长时间写好的组件,我们不希望他被别人随意改动,但是如果完全封闭,那么就失去了组件的封装性,那组件也就没有丝毫意义可言了。但是如果我们整个的暴露所有代码实现,那么可能导致很多超出我们预料的问题,所以我们可以仿照Java的模式来做,暴露部分接口,这样不仅保证了组件的稳定,也可以达到封装的目的。就拿我大学期间的做的一个图书管理系统代码:

```javascript//书籍分类GLOBAL.comm.comnav=(function(){var bindNav=function(navList){$.each(navList,function(key,val){$("#"+val.split("-")[0]+">span").click(function(){$(this).siblings().each(function(){$(this).find(".active").hide().siblings().find("[_tag="+$(this).attr("_tag")+"]").removeClass("red");});$(this).find(".active").show().siblings().find("[_tag="+$(this).attr("_tag")+"]").addClass("red");showTag([val.split("-")[1],val.split("-")[2]],$(this).attr("_tag"));});});};var processNav=function(navId,commId,listId){return navId + "-" + commId + "-" +listId;};var showTag=function(tagList,tagName){$.each(tagList,function(index){$("#"+tagList[index]).find("[_tag="+tagName+"]").show().siblings().hide();});};return {init:bindNav,newInstantce:processNav}})();
```

这是我当时基于JQ做的一个项目中部分代码(要喷,请轻点。。),在这段代码中我是基于return 来实现暴露接口,暴露了init和newInstantce,而其他方法对外是完全不可见的。而具体的调用代码如下:

```javascript//推荐类型切换index.comNavChg = function(){GLOBAL.comm.comnav.init([GLOBAL.comm.comnav.newInstantce("hottabs","recommends","hotlist")]);}
```

以上的调用代码只利用到了comnav中暴露的两个方法,而具体的代码实现对外是不可见的。以上代码由于我是包装了return的函数,所以他形成了一个闭包(通过闭包来访问内部数据),这也就变相的实现了private。

即时函数

在上面图书管理的实例代码中,大家可能注意到我所有的逻辑都是写在Global这个命名空间下,但是很多情况下,例如写JQ的插件的时候,我们并要保证他在别人引用时都能正常运行,所以我们就要考虑新的方法。即时函数时一个很好的解决方案,他一般用来解决只允许运行一次的情况,例如打开很多巨头网站在console上面显示招聘信息的代码,他并不和任何业务代码产生交集,也很好的防止了污染全局变量(因为他为里面的代码提供了一个作用域沙箱)。下面我们来看dnspod的效果:

o_QQ%e6%88%aa%e5%9b%be20140122051744.png

很酷吧,我们来看看它的具体代码实现:

```javascript(function(){try{if(window.console && window.console.log){console.log('             Qv.                                                      \n             ZBjIjv;           ..,..                                  \n              @yizero.mFLIEmQ0qFFzSuFFZZqFSl;                         \n              yBzl;vvvczFIv;::,:,:::::::: @haohu.                     \n               BZFCvvvc;:,::;;;;;;;:;:;;;;     ;Zbu.                  \n               7BuNNv7;::;;;;:::,,,,,::::;;       IBO.                \n              .D0zFv7;::;:,.:;v7jjVyCslv;:::;.    .:jBF               \n             :BqVNvvv:::,;sCzZFuIysLsVzZZ0Fl;;:;;v;;,:0B              \n             bZVFlv7v,.vmOSBs           ..;bB0z:,;;;;:.jB             \n            @kevensun.SBv  BjQ:          vEEq VBl,:;;;:.jB            \n            BFzFs;7vvZb   sI  0b;      ;bF  B  ,BI,:;;;:.BV           \n            BFVFvvvvvB.   D.  ;bCm:  ;0Nb   N;  .B;:;;;;.lB           \n            bNzFvv7vlB.   BZ  q;  EO8F  R   Bj   #N.;;;;:;B           \n            0ByF7vvv;bF   BBBCb   @Wwz  7qSBBD   B;;;;,7B           \n         lRu7BNzV;vvvvBZ ;BBBBR ;B;  vB  bBBBB  BE,:;;;,,BZ           \n        Eb:. ;BFzj;vvv;0EBBBBB;:D     .#:RBBBBNRS,:;;;,:ZB            \n       mE.,,: ;REylvvvv;vLObBBbz        NBBBBDC;.:::::;EB,            \n       B..,:::..SbFc;vvvv;:;vCENZOZNFZNSy0s;.  ,,::;;IBB              \n       D8:.,:,,  ;O#F;;;vvv;;;;v7ljjyjsv;,,,;;;;v;vsRBl  ,vvvv;       \n        lDOl;vsu;  :jbF7;;;;;vvvvvvvvvvvvvvvvv;v7V8BV  ;bZsjsjzBl     \n          ;ySVlvEEc .BOBbZzlv;;;;;;;;;;;;;vvsjNEDbBl7suq;.,,,,.,B;    \n                 ,IZBQc8EF0R @guohezou.08DRDQ#BsZ0  ...,:::::,.Ez    \n                    BRV#OjzVFuDBbbbQENZZEZqSuLN8sqB.;;;,,,::::: DC    \n                    .ZOBQSzIcv;RZ.vyIVCClvvyVzZBqB#jCuVBs,.,,,.vb,    \n                       7#;v;v;;;0s     ;7qF:vvOQv,       @arqiao.     \n                       lq,;;;;;:EQ ;BEb  R7;;,Ss          ,:,,        \n                       LBjuVSVCOB ,BEB; zBsyFzBy                      \n                       uBzVFzzNB       ,BVmBbbBBc                     \n                       zBCuzuCBmvzZOQ8bBFO8v;;  7EC                   \n                       SBCICsLLVNZZZFFjIBF:;vv    #Z                  \n                       .RNFzzy @kexianli.:;;;v7;;,0b                  \n                            BEuuIBj    BOFCjcllyI#B.                  \n                            Bs;;;CB.   :@secbone.b                    \n                           RZvv7;;vQR    IBB#RbBy                     \n                          BZ;v7v,.. Bc     :vv;                       \n                          RL;;vv;;:;NZ                                \n                          Fmv7l7ssIjqBBqv                             \n                         NBBOzIVVSu0bBbBBB                            \n                         jBbBBBbBbBBBBBBBB                            \n                           .vuqQ8DQEZuc;                              \n\n');console.log('Hi~ 欢迎加入DNSPod,简历请发送至 %c hr@dnspod.com','color:#4FA6E7');}}catch(e){}})()
```

额,虽然只是文字把戏,可是别人也做的很用心,这种代码用即时函数来做,是再好不过了(感兴趣的童鞋可以把上面的代码拉倒console里面去试试)。

下面我们来了解下即时函数的写法,代码如下:

```javascript//第一种形式(function() {//body})();//第二种形式(function(){}());
```

上面2种模式没有太大的区别,我喜欢使用第一种(看上去更像是执行一个函数) ,但是JSLint偏好使用第二种。这种模式本质上只是一个函数表达式(详细请看上一篇)。

同样的,既然他也是函数,那么我们一样可以给他传参,在JQ插件中更多的是给他指定作用域。代码示例如下:

```javascript(function(window, document, undefined) {function Wr(element, opts) {return (this instanceof Wr) ? this.init(element, opts) : new Wr(element, opts);}Wr.prototype.init = function(){// body ...};//other code })(window, window.document);
```

同样的很多模块化代码的实现中,也大量利用到了即时函数(用以区分不同模块)。

结语

这一篇,我总结了下工作中包括了解到的一些函数的编程用法,总体的是想加强自己在JS结构方面的认识,希望加深自己对JS模块化的认识。如有错误,请指正。下一篇我将总结一下JS中函数的一些高级用法。

转载于:https://www.cnblogs.com/ahjx777/p/3529142.html

这篇关于初涉JavaScript模式 (9) : 函数 【常用方式】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja