热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:函数式编程与Js异步编程手写Promise

本文由编程笔记#小编为大家整理,主要介绍了函数式编程与Js异步编程手写Promise相关的知识,希望对你有一定的参考价值。Part1·
本文由编程笔记#小编为大家整理,主要介绍了函数式编程与Js异步编程手写Promise相关的知识,希望对你有一定的参考价值。



Part1 · Javascript【深度剖析】

函数式编程与Js异步编程、手写Promise

文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区指出,如果您觉得专栏内容还不错,请点赞、关注、评论。

共同进步!


文章目录




  • Part1 · Javascript【深度剖析】


  • 函数式编程与Js异步编程、手写Promise



    • @[toc]



  • 一、为什么要学习函数式编程


  • 二、什么是函数式编程


  • 三、前置知识



    • 1.函数是一等公民


    • 2.高阶函数



      • 什么是高阶函数


      • 使用高阶函数的意义


      • 常用的高阶函数



    • 3.闭包




一、为什么要学习函数式编程

函数式编程功能是非常古老的一个概念,早于第一台计算机的诞生,函数式编程的历史

学习函数式编程的目的:



  • 函数式编程是随着React的流行受到越来越多的关注;


  • Vue3也开始走入函数式编程的怀抱;


  • 函数式编程可以抛弃this


  • 打包过程中可以更好的利用tree shaking过滤无用的代码


  • 方便测试、方便并行处理


  • 有很多库可以帮助我们进行函数式开发:lodash、underscore、ramda





二、什么是函数式编程

函数式编程(Functional Programming,FP),FP是编程范式之一,常说的编程范式还有面向过程编程、面向对象编程。



  • 【面向对象编程】的思维模式:把现实世界中的失误抽象成程序世界中的类和对象,通过封装、继承和多态来演示事务事件的联系(人类-小明)


  • 【函数式编程】的思维方式:把现实世界的事务和事务之间的联系抽象到程序世界(对运算过程进行抽象)



    • 程序的本质:根据输入通过某种运算获得相应的输出,程序开发过程中会涉及很多有输入和输出的函数


    • x -> f(联系、映射) -> y, y=f(x)


    • 函数式编程中的函数指的不是程序中的函数(或方法),而是数学中的函数即映射关系,例如:y=sin(x),x和y的关系


    • 相同的输入始终得到相同的输出(纯函数)


    • 函数式编程用来描述数据(函数)之间的映射



// 非函数式
let num1 = 2;
let num2 = 3;
let sum = num1 + num2;
console.log(sum);
// 函数式
function add(n1, n2) {
return n1 + n2
}
let sum = add(2, 3);
console.log(sum);



三、前置知识

1.函数是一等公民

MDN First-class Function

在Javascript中函数就是一个普通的对象(可以通过new Function()),我们可以把函数存储到变量、数组中,它还可以作为另一个函数的参数和返回值,甚至我们可以在程序运行的时候通过new Function(‘alert(1)’)来构造一个新的函数



  • 函数可以存储在变量中


  • 函数作为参数


  • 函数作为返回值


  • 把函数赋值给变量


// 把函数赋值给变量
let fn = function () {
console.log('Hello First-class Function')
}
fn() // 函数调用
// 示例
const BlogController = {
index(posts) {return views.index(ports)},
show (post) { return Views.show(post) },
create (attrs) { return Db.create(attrs) },
update (post, attrs) { return Db.update(post, attrs) },
destroy (post) { return Db.destroy(post) }
}
// 示例优化
const BlogController = {
index: Views.index,
show: Views.show,
create: Db.create,
update: Db.update,
destroy: Db.destroy
}


  • 函数是一等公民是后面学习高阶函数、函数柯里化的基础



2.高阶函数


什么是高阶函数



  • 高阶函数(Higher-order Function)



    • 可以把函数作为参数传递给另一个函数


    • 可以把函数作为另一个函数的返回结果



  • 函数作为参数


// 模拟forEach
function forEach(array, fn){
for (let i = 0;i < array.length; i++) {
fn(array[i])
}
}
// 模拟filter
function filter(array, fn) {
let results = [];
for (let i = 0; i < array.length; i++){
if (fn(array[i])) {
results.push(array[i])
}
}
return results;
}


  • 函数作为返回值


function makeFn(){
let msg = 'Hello Function';
return function () {
console.log(msg)
}
}
const fn = makeFn();
fn()

// once模拟支付,业务场景中用户支付次数只允许为一次
function once(fn){
let done = false; // 默认置为false
return function (){
if (!done){
// 若未支付,则进入函数
done = true; // 进入后,将done置为true,确保下次不进入函数
return fn.apply(this, arguments)
}
}
}
let pay = once(function (money)){
console.log('支付:' + money + 'RMB';
}
// 只会打印一次
pay(5);
pay(5);
pay(5);

apply函数提示

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

注意:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
console.log(max);
// expected output: 7
const min = Math.min.apply(null, numbers);
console.log(min);
// expected output: 2
// 详情查看MDN:
// https://developer.mozilla.org/zh-CN/docs/Web/Javascript/Reference/Global_Objects/Function/apply

使用高阶函数的意义




  • 高阶函数是用来抽象通用的问题


// 面向过程的方式
let array = [1, 2, 3, 4];
for (let i = 0; i < array.length;i++) {
console.log(array[i])
}
// 高阶函数
let array = [1, 2, 3, 4];
forEach(array, item) =>{
console.log(item)
}
let r = filter(array, item) =>{
return irem % 2 === 0
}

常用的高阶函数



  • forEach


  • map


  • filter


  • every


  • some


  • find/findIndex


  • reduce


  • sort



// map函数
const map = (array, fn) => {
let results = []
for (const value of array) {
results.push(fn(value))
}
return results
}
// every函数
const every = (array, fn) =>{
let result = true;
for (const value of array) {
result = fn(value);
if (!result) {
break
}
}
return result
}
// some函数
const some = (array, fn) =>{
let result = false;
for (conse value of array) {
result = fn(value);
if (result) {
break
}
}
return result
}

3.闭包



  • 闭包(Closure):函数和其周围的状态(词法环境)的引用捆绑在一起形成闭包。

    // 函数作为返回值
    function makeFn() {
    let msg = 'Hello Function';
    return function () {
    console.log(msg)
    }
    }
    const fn = makeFn();
    fn()
    // once
    function once(fn) {
    let done = false;
    return function (){
    if (!done) {
    return fn.apply(this, arguments)
    }
    }
    }
    let pay = once(function (money) {
    console.log('支付:' + money + 'RMB')
    })
    // 只会支付一次
    pay(5);
    pay(5);



    • 可以在另一个作用域中调用一个函数的内部函数并访问到高函数的作用域中的成员



  • 闭包的本质:函数在执行的时候会放到一个执行栈上,当函数执行完毕后会从执行栈上移出,但是堆上的作用域成员因为被外部引用不能释放,因此内部函数依然可以访问外部函数的成员


  • 闭包案例


// 生成计算数字多少次幂的函数
function makePower(power) {
return function (x) {
return Matn.pow(x, power)
}
}
let power2 = makePower(2);
let power3 = makePower(3);
console.log(power2(4))
console.log(power3(4))
// 第一个函数是基本工资,第二个函数是绩效工资
function makeSalary(x) {
return function (y) {
return x + y
}
}
let salaryLevel1 = makeSalary(1500);
let salaryLevel2 = makeSalary(2000);
console.log(alaryLevel1(2000))
console.log(alaryLevel1(3000))

今日分享截止到这里,明天继续更新后续部分:纯函数、柯里化、函数组合、Functor。

记录:2020/11/14



推荐阅读
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • React项目中运用React技巧解决实际问题的总结
    本文总结了在React项目中如何运用React技巧解决一些实际问题,包括取消请求和页面卸载的关联,利用useEffect和AbortController等技术实现请求的取消。文章中的代码是简化后的例子,但思想是相通的。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
    2OpenvSwitch架构2.1OVS整体架构ovs-vswitchd:守护程序,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换flow-basedswitchin ... [详细]
  • 简述在某个项目中需要分析PHP代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑ÿ ... [详细]
  • 求解连通树的最小长度及优化
    本文介绍了求解连通树的最小长度的方法,并通过四边形不等式进行了优化。具体方法为使用状态转移方程求解树的最小长度,并通过四边形不等式进行优化。 ... [详细]
  • 本文详细介绍了在Linux虚拟化部署中进行VLAN配置的方法。首先要确认Linux系统内核是否已经支持VLAN功能,然后配置物理网卡、子网卡和虚拟VLAN网卡的关系。接着介绍了在Linux配置VLAN Trunk的步骤,包括将物理网卡添加到VLAN、检查添加的VLAN虚拟网卡信息以及重启网络服务等。最后,通过验证连通性来确认配置是否成功。 ... [详细]
author-avatar
偶们滴小圈子6868
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有