我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JS如何实现XDM

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JS如何实现XDM

这篇文章主要介绍“JS如何实现XDM”,在日常操作中,相信很多人在JS如何实现XDM问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS如何实现XDM”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

偏函数

传参现状

我们经常会写出这样的代码:

function ajax(url,data,callback) {    // ..}function getPerson(data,cb) {    ajax( "http://some.api/person", data, cb );}

ajax 函数有三个入参,在 getPerson 函数里调用,其中 url 已确定,data 和 cb 两个参数则等待传入。(因为很多时候参数都不是在当前能确定的,需要等待其它函数的操作后确定了再继续传入)

但是我们的原则是:入参最理想的情况下只需一个!

怎样优化,可以实现这一点呢?

我们或许可以在外层再套一个函数来进一步确定传参,比如:

function getCurrentUser(cb) {    ...// 通过某些操作拿到 CURRENT_USER_ID    getPerson( { user: CURRENT_USER_ID }, cb );}

这样,data 参数也已经确定,cb 参数仍等待传入;函数 getCurrentUser 就只有一个入参了!

数据的传递路线是:

ajax(url,data,callback) => getPerson(data,cb) => getCurrentUser(cb)

这样函数参数个数逐渐减少的过程就是偏应用。

也可以说:getCurrentUser(cb) 是 getOrder(data,cb) 的偏函数,getOrder(data,cb) 是 ajax(url,data,cb) 函数的偏函数。

设想下:

如果一个函数是这样的:

function receiveMultiParam(a,b,c,......,x,y,z){    // ..}

我们难道还要像上面那样手动指定外层函数进行逐层嵌套吗?

显示我们不会这么做!

封装 partial

我们只需要封装一个 partial(..) 函数:

function partial(fn,...presetArgs) {    return function partiallyApplied(...laterArgs){        return fn( ...presetArgs, ...laterArgs );    };}

它的基础逻辑是:

var partial =    (fn, ...presetArgs) =>        (...laterArgs) =>            fn( ...presetArgs, ...laterArgs );

把函数作为入参!还记得我们之前所说:

一个函数如果可以接受或返回一个甚至多个函数,它被叫做高阶函数。

我们借用 partial() 来实现上述举例:

var getPerson = partial( ajax, "http://some.api/person" );var getCurrentUser = partial( getPerson, { user: CURRENT_USER_ID } ); // 版本 1

以下函数内部分析非常重要:

运行机制

getPerson() 的内部运行机制是:

var getPerson = function partiallyApplied(...laterArgs) {    return ajax( "http://some.api/person", ...laterArgs );};

getCurrentUser() 的内部运行机制是:

var getCurrentUser = function outerPartiallyApplied(...outerLaterArgs) {    var getPerson = function innerPartiallyApplied(...innerLaterArgs){        return ajax( "http://some.api/person", ...innerLaterArgs );    };    return getPerson( { user: CURRENT_USER_ID }, ...outerLaterArgs );}

数据进行了传递:

getCurrentUser(outerLaterArgs) => getPerson(innerLaterArgs) => ajax(...params)

我们通过这样一层额外的函数包装层,实现了更加强大的数据传递,

我们将需要减少参数输入的函数传入 partial()中作为第一个参数,剩下的是 presetArgs,当前已知几个,就可以写几个。还有不确定的入参 laterArgs,可以在确定后继续追加。

像这样进行额外的高阶函数包装层,是函数式编程的精髓所在!

“随着本系列的继续深入,我们将会把许多函数互相包装起来。记住,这就是函数式编程!” —— 《JavaScript 轻量级函数式编程》

实际上,实现 getCurrentUser() 还可以这样写:

// 版本 2var getCurrentUser = partial(    ajax,    "http://some.api/person",    { user: CURRENT_USER_ID });// 内部实现机制var getCurrentUser = function partiallyApplied(...laterArgs) {    return ajax(        "http://some.api/person",        { user: CURRENT_USER_ID },        ...laterArgs    );};

但是版本 1 因为重用了已经定义好的函数,所以它在表达上更清晰一些。它被认为更加贴合函数式编程精神!

拓展 partial

我们再看看 partial() 函数还可它用:

function partial(fn,...presetArgs) {    return function partiallyApplied(...laterArgs){        return fn( ...presetArgs, ...laterArgs );    };}

比如:将数组 [1,2,3,4,5] 每项都加 3,通常我们会这么做:

function add(x,y) {    return x + y[1,2,3,4,5].map( function adder(val){    return add( 3, val );} );// [4,5,6,7,8]

借助 partial():

[1,2,3,4,5].map( partial( add, 3 ) );// [4,5,6,7,8]

add(..) 不能直接传入 map(..) 函数里,通过偏应用进行处理后则能传入;

实际上,partial() 函数还可以有很多变体:

回想我们之前调用 Ajax 函数的方式:ajax( url, data, cb )。如果要偏应用 cb 而稍后再指定 data 和 url 参数,我们应该怎么做呢?

function reverseArgs(fn) {    return function argsReversed(...args){        return fn( ...args.reverse() );    };}function partialRight( fn, ...presetArgs ) {    return reverseArgs(        partial( reverseArgs( fn ), ...presetArgs.reverse() )    );}var cacheResult = partialRight( ajax, function onResult(obj){    cache[obj.id] = obj;});// 处理后:cacheResult( "http://some.api/person", { user: CURRENT_USER_ID } );

柯里化

函数柯里化实际上是一种特殊的偏函数。

我们用 curry(..) 函数来实现此前的 ajax(..) 例子,它会是这样的:

var curriedAjax = curry( ajax );var personFetcher = curriedAjax( "http://some.api/person" );var getCurrentUser = personFetcher( { user: CURRENT_USER_ID } );getCurrentUser( function foundUser(user){  } );

柯里化函数:接收单一实参(实参个数:1)并返回另一个接收下一个实参的函数。

它将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。

实现:

function curry(fn,arity = fn.length) {    return (function nextCurried(prevArgs){        return function curried(nextArg){            var args = prevArgs.concat( [nextArg] );            if (args.length >= arity) {                return fn( ...args );            }            else {                return nextCurried( args );            }        };    })( [] );}

到此,关于“JS如何实现XDM”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JS如何实现XDM

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JS如何实现XDM

这篇文章主要介绍“JS如何实现XDM”,在日常操作中,相信很多人在JS如何实现XDM问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS如何实现XDM”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!偏函数传参
2023-07-02

怎么使用JS函数式编程实现XDM

这篇文章主要讲解了“怎么使用JS函数式编程实现XDM”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用JS函数式编程实现XDM”吧!FP 概览重要性函数式编程(FP),不是一个新的概念,
2023-07-02

js如何实现深拷贝

这篇文章给大家分享的是有关js如何实现深拷贝的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。深拷贝使用变量 a 拷贝对象 b,改变 a 中的值 b 中的值也会跟着改变,这叫做浅拷贝。要想让 a 独立于 b 就需要深
2023-06-27

JS如何实现轮播图

本篇内容介绍了“JS如何实现轮播图”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!实现功能:1、自动轮播:鼠标停留在轮播图上时不切换图片,鼠标
2023-06-29

js如何实现封装jQuery

这篇文章将为大家详细讲解有关js如何实现封装jQuery,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。本文js实现了下面jquery的几种方法,我将它分为8个小目标实现$(".box1").click(
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录