javascript实用库_编写实用JavaScript的实用指南

javascript实用库

by Nadeesha Cabral

通过Nadeesha Cabral

编写实用JavaScript的实用指南 (A practical guide to writing more functional JavaScript)

Functional programming is great. With the introduction of React, more and more JavaScript front-end code is being written with FP principles in mind. But how do we start using the FP mindset in everyday code we write? I’ll attempt to use an everyday code block and refactor it step by step.

函数式编程很棒。 随着React的引入,越来越多JavaScript前端代码是根据FP原理编写的。 但是,如何在编写的日常代码中开始使用FP思维方式? 我将尝试使用日常代码块并逐步对其进行重构。

Our problem: A user who comes to our /login page will optionally have a redirect_to query parameter. Like /login?redirect_to=%2Fmy-page. Note that %2Fmy-page is actually /my-page when it’s encoded as the part of the URL. We need to extract this query string, and store it in local storage, so that once the login is done, user can be redirected to the my-page.

我们的问题:进入/login页面的用户可以选择使用redirect_to查询参数。 像/login?redirect_to=%2Fmy-page 。 请注意, %2Fmy-page编码为URL的一部分时,实际上是/my-page 。 我们需要提取此查询字符串,并将其存储在本地存储中,以便完成登录后,可以将用户重定向到my-page

步骤0:当务之急 (Step 0: The imperative approach)

If we had to express the solution in the simplest form of issuing a list of commands, how would we write it? We will need to

如果我们必须以发布命令列表的最简单形式来表达解决方案,那么我们将如何编写它呢? 我们将需要

  1. Parse the query string.

    解析查询字符串。
  2. Get the redirect_to value.

    获取redirect_to值。

  3. Decode that value.

    解码该值。
  4. Store the decoded value in localStorage.

    将解码后的值存储在localStorage中。

And we have to put try catch blocks around “unsafe” functions as well. With all of that, our code block will look like:

而且我们还必须围绕“不安全”功能放置尝试捕获块。 有了这些,我们的代码块将看起来像:

步骤1:将每个步骤编写为函数 (Step 1: Writing every step as a function)

For a moment, let’s forget the try catch blocks and try expressing everything as a function here.

暂时,让我们忘记try catch块,并尝试在此处将所有内容表示为一个函数。

When we start expressing all of our “outcomes” as results of functions, we see what we can refactor out of our main function body. When that happens, our function becomes much easier to grok, and much easier to test.

当我们开始将所有“结果”表达为功能的结果时,我们看到可以从我们的主要功能主体中进行重构。 发生这种情况时,我们的功能将变得更容易使用,也更易于测试。

Earlier, we would have tested the main function as a whole. But now, we have 4 smaller functions, and some of them are just proxying other functions, so the footprint that needs to be tested is much smaller.

之前,我们将测试整个主要功能。 但是现在,我们有4个较小的功能,其中一些只是代理其他功能,因此需要测试的占地面积要小得多。

Let’s identify these proxying functions, and remove the proxy, so we have a little bit less code.

让我们识别这些代理功能,并删除代理,这样我们的代码就会少一点。

步骤2:尝试编写功能 (Step 2: An attempt at composing functions)

Alright. Now, it seems like the persistRedirectToParams function is a “composition” of 4 other functions. Let’s see whether we can write this function as a composition, thereby eliminating the interim results we store as consts.

好的。 现在,似乎persistRedirectToParams函数是其他4个函数的“组合”。 让我们看看是否可以将此函数编写为一个组合,从而消除我们存储为const的中期结果。

This is good. But I feel for the person who reads this nested function call. If there was a way to untangle this mess, that’d be awesome.

很好 但是我对阅读此嵌套函数调用的人有感觉。 如果有办法解开这个烂摊子,那就太好了。

步骤3:更具可读性的构图 (Step 3: A more readable composition)

If you’ve done some redux or recompose, you’d have come across compose. Compose is a utility function which accepts multiple functions, and returns one function that calls the underlying functions one by one. There are other excellent sources to learn about composition, so I won’t go into detail about that here.

如果您做了一些还原或重组,就会碰到compose 。 Compose是一种实用程序函数,它接受多个函数,并返回一个函数,该函数一个接一个地调用基础函数。 还有其他一些很好的资料可以学习构图,因此在这里我将不做详细介绍。

With compose, our code will look like:

使用compose,我们的代码将如下所示:

One thing with compose is that it reduces functions right-to-left. So, the first function that gets invoked in the compose chain is the last function.

compose的一件事是它从右到左减少了功能。 因此,在compose链中被调用的第一个函数是最后一个函数。

This is not a problem if you’re a mathematician, and are familiar with the concept, so you naturally read this right-to-left. But for the rest of us familiar with imperative code, we would like to read this left-to-right.

如果您是数学家并且熟悉该概念,那么这不是问题,因此您自然而然地从右到左阅读。 但是对于熟悉命令式代码的其他人,我们想从左至右阅读。

步骤4:管道和展平 (Step 4: Piping and flattening)

Luckily, there’s pipe. pipe does the same thing that compose does, but in reverse. So, the first function in the chain is the first function processing the result.

幸运的是,那里有pipepipe执行与compose相同的操作,但是相反。 因此,链中的第一个功能是处理结果的第一个功能。

Also, it seems as if our persistRedirectToParams function has become a wrapper for another function that we call op. In other words, all it does is execute op. We can get rid of the wrapper and “flatten” our function.

同样,似乎我们的persistRedirectToParams函数已成为另一个称为op函数的包装。 换句话说,它所做的就是执行op 。 我们可以摆脱包装器并“展平”我们的功能。

Almost there. Remember, that we conveniently left our try-catch block behind to get this to the current state? Well, we need some way to introduce it back. qs.parse is unsafe as well as storeRedirectToQuery. One option is to make them wrapper functions and put them in try-catch blocks. The other, functional way is to express try-catch as a function.

差不多了。 还记得吗,我们方便地将try-catch块留在了后面,以使其处于当前状态? 好吧,我们需要一些方法来介绍它。 qs.parse是不安全以及storeRedirectToQuery 。 一种选择是使它们具有包装器功能,并将其放入try-catch块中。 另一种功能性方法是将try-catch表示为一个功能。

步骤5:异常处理功能 (Step 5: Exception handling as a function)

There are some utilities which do this, but let’s try writing something ourselves.

有一些实用程序可以做到这一点,但让我们尝试自己编写一些东西。

Our function here expects an opts object which will contain tryer and catcher functions. It will return a function which, when invoked with arguments, call the tryer with the said arguments and upon failure, call the catcher. Now, when we have unsafe operations, we can put them in the tryer section and if they fail, rescue and give a safe result from the catcher section (and even log the error).

我们的函数在这里需要一个opts对象,其中将包含tryercatcher函数。 它将返回一个函数,当使用参数调用该tryer ,将使用所述参数调用该tryer ,并在失败时调用该catcher 。 现在,当我们进行不安全的操作时,我们可以将它们放在tryer部分中,如果它们失败,请从catcher部分进行救援并给出安全的结果(甚至记录错误)。

步骤6:将所有内容放在一起 (Step 6: Putting everything together)

So, with that in mind, our final code looks like:

因此,考虑到这一点,我们的最终代码如下所示:

This is more or less what we want. But to make sure the readability and testability of our code improves, we can factor out the “safe” functions as well.

这或多或少是我们想要的。 但是,要确保提高代码的可读性和可测试性,我们还可以考虑“安全”功能。

Now, what we’ve got is an implementation of a much larger function, consisting of 4 individual functions that are highly cohesive, loosely coupled, can be tested independently, can be re-used independently, account for exception scenarios, and are highly declarative. (And IMO, they’re a tad bit nicer to read.)

现在,我们得到的是一个更大功能的实现,该功能由4个高度凝聚,松散耦合,可以独立测试,可以独立重用,说明异常情况且具有高度声明性的单个功能组成。 (而且IMO,它们的阅读性更好一点。)

There’s some FP syntactic sugar that makes this even nicer, but that’s for another day.

有一些FP语法糖使它变得更好,但这是另一天的事情。

翻译自: https://www.freecodecamp.org/news/a-practical-guide-to-writing-more-functional-javascript-db49409f71/

javascript实用库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库数据过长避免_为什么要避免使用商业数据科学平台

数据库数据过长避免让我们从一个类比开始 (Lets start with an analogy) Stick with me, I promise it’s relevant.坚持下去,我保证这很重要。 If your selling vegetables in a grocery store your business value lies in your loyal customers and your positi…

mysql case快捷方法_MySQL case when使用方法实例解析

首先我们创建数据库表: CREATE TABLE t_demo (id int(32) NOT NULL,name varchar(255) DEFAULT NULL,age int(2) DEFAULT NULL,num int(3) DEFAULT NULL,PRIMARY KEY (id)) ENGINEInnoDB DEFAULT CHARSETutf8;插入数据:INSERT INTO t_demo VALUES (1, 张…

【~~~】POJ-1006

很简单的一道题目,但是引出了很多知识点。 这是一道中国剩余问题,先贴一下1006的代码。 #include "stdio.h" #define MAX 21252 int main() { int p , e , i , d , n 1 , days 0; while(1) { scanf("%d %d %d %d",&p,&e,&…

Java快速扫盲指南

文章转自:https://segmentfault.com/a/1190000004817465#articleHeader22 JDK,JRE和 JVM 的区别 JVM:java 虚拟机,负责将编译产生的字节码转换为特定机器代码,实现一次编译多处执行; JRE:java运…

xcode扩展_如何将Xcode插件转换为Xcode扩展名

xcode扩展by Khoa Pham通过Khoa Pham 如何将Xcode插件转换为Xcode扩展名 (How to convert your Xcode plugins to Xcode extensions) Xcode is an indispensable IDE for iOS and macOS developers. From the early days, the ability to build and install custom plugins ha…

leetcode 861. 翻转矩阵后的得分(贪心算法)

有一个二维矩阵 A 其中每个元素的值为 0 或 1 。 移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。 在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩…

数据分析团队的价值_您的数据科学团队的价值

数据分析团队的价值This is the first article in a 2-part series!!这是分两部分的系列文章中的第一篇! 组织数据科学 (Organisational Data Science) Few would argue against the importance of data in today’s highly competitive corporate world. The tech…

mysql 保留5位小数_小猿圈分享-MySQL保留几位小数的4种方法

今天小猿圈给大家分享的是MySQL使用中4种保留小数的方法,希望可以帮助到大家,让大家的工作更加方便。1 round(x,d)用于数据x的四舍五入, round(x) ,其实就是round(x,0),也就是默认d为0;这里有个值得注意的地方是,d可以是负数&…

leetcode 842. 将数组拆分成斐波那契序列(回溯算法)

给定一个数字字符串 S&#xff0c;比如 S “123456579”&#xff0c;我们可以将它分成斐波那契式的序列 [123, 456, 579]。 形式上&#xff0c;斐波那契式序列是一个非负整数列表 F&#xff0c;且满足&#xff1a; 0 < F[i] < 2^31 - 1&#xff0c;&#xff08;也就是…

博主简介

面向各层次&#xff08;从中学到博士&#xff09;提供GIS和Python GIS案例实验实习培训&#xff0c;以解决问题为导向&#xff0c;以项目实战为主线&#xff0c;以科学研究为思维&#xff0c;不讲概念&#xff0c;不局限理论&#xff0c;简单照做&#xff0c;即学即会。 研究背…

自定义Toast 很简单就可以达到一些对话框的效果 使用起来很方便

自定义一个layout布局 通过toast.setView 设置布局弹出一些警示框 等一些不会改变的提示框 很方便public class CustomToast {public static void showUSBToast(Context context) {//加载Toast布局 View toastRoot LayoutInflater.from(context).inflate(R.layout.toas…

微信小程序阻止冒泡点击_微信小程序bindtap事件与冒泡阻止详解

bindtap就是点击事件在.wxml文件绑定:cilck here在一个组件的属性上添加bindtap并赋予一个值(一个函数名)当点击该组件时, 会触发相应的函数执行在后台.js文件中定义tapMessage函数://index.jsPage({data: {mo: Hello World!!,userid : 1234,},// 定义函数tapMessage: function…

同情机器人_同情心如何帮助您建立更好的工作文化

同情机器人Empathy is one of those things that can help in any part of life whether it’s your family, friends, that special person and even also at work. Understanding what empathy is and how it effects people took me long time. I struggle with human inter…

数据库课程设计结论_结论

数据库课程设计结论When writing about learning or breaking into data science, I always advise building projects.在撰写有关学习或涉足数据科学的文章时&#xff0c;我总是建议构建项目。 It is the best way to learn as well as showcase your skills.这是学习和展示技…

mongo基本使用方法

mongo与关系型数据库的概念对比&#xff0c;区分大小写&#xff0c;_id为主键。 1.数据库操作 >show dbs #查看所有数据库 >use dbname #创建和切换数据库&#xff08;如果dbname存在则切换到该数据库&#xff0c;不存在则创建并切换到该数据库&#xff1b;新创建的…

leetcode 62. 不同路径(dp)

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为“Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为“Finish”&#xff09;。 问总共有多少条不同的路径&#xff1f; 例如&…

第一名数据科学工作冠状病毒医生

背景 (Background) 3 years ago, I had just finished medical school and started working full-time as a doctor in the UK’s National Health Service (NHS). Now, I work full-time as a data scientist at dunnhumby, writing code for “Big Data” analytics with Pyt…

mysql时间区间效率_对于sql中使用to_timestamp判断时间区间和不使用的效率对比及结论...

关于日期函数TO_TIMESTAMP拓展&#xff1a;date类型是Oracle常用的日期型变量&#xff0c;时间间隔是秒。两个日期型相减得到是两个时间的间隔&#xff0c;注意单位是“天”。timestamp是DATE类型的扩展&#xff0c;可以精确到小数秒(fractional_seconds_precision)&#xff0c…

ajax 赋值return

ajax 获得结果后赋值无法成功&#xff0c; function grades(num){ var name"";   $.ajax({    type:"get",     url:"",     async:true,     success:function(result){     var grades result.grades;     …

JavaScript(ES6)传播算子和rest参数简介

by Joanna Gaudyn乔安娜高登(Joanna Gaudyn) JavaScript(ES6)传播算子和rest参数简介 (An intro to the spread operator and rest parameter in JavaScript (ES6)) 扩展运算符和rest参数都被写为三个连续的点(…)。 他们还有其他共同点吗&#xff1f; (Both the spread opera…