资讯专栏INFORMATION COLUMN

让函数进化

alin / 1883人阅读

摘要:匿名函数访问和则是典型的闭包的应用,并没有把函数存储在任何典型的数据结构中。另外,每添加一个函数,就会增加一层嵌套,调用深度过深的话性能开销也会比较大,使用的时候要进行权衡。

本文同步自我的 GitHub

假设现在有这样一个场景,一个下单页面,需要根据特定的条件去计算购物车商品的总价,特定的条件包括但不限于选中的商品、是否选择折扣、是否叠加套餐和运费险等。这时我们通常需要写一个用来计算总价的函数getTotalPrice(),然而,函数的参数是不确定的,同时函数内的逻辑也会根据参数的不同而有所变化,最简单的方法是在函数内部对参数进行判断:

如果参数分开传入,那么函数的伪代码可能写成这样:

function getTotalPrice(selectedGoods, isDiscounted, pacakge) {
    var totalPrice = 0;
    if (selectedGoods) {
        totalPrice = ...;
        if (isDiscounted) {
            // 计算折扣
            if (package) {...}
        } else if (pacakge) {...}
        return totalPrice;
    } else {
        return 0;
    }
}

有的人可能觉得将参数分开传入函数看起来比较乱,会习惯用一个参数对象包裹一下,在函数内部再对这个对象进行解析。看起来确实有一定的改进,但我认为并没有什么本质上的区别。

现在希望能够做到针对不同参数的情况,在函数内部只书写针对特定个数参数的逻辑,不去写乱七八糟的if-else语句或是参数对象的解析逻辑。同时,这些函数共用一个函数名,并且该逻辑可扩展,即可以随时根据需要,添加函数。

通过对需求的分析,应该会有这样的一个工具函数:

var methods = {};

addFunction(methods, "getTotalPrice", function(selectedGoods) {...});
addFunction(methods, "getTotalPrice", function(selectedGoods, isDiscounted) {...});
addFunction(methods, "getTotalPrice", function(selectedGoods, isDiscounted, pacakge) {...});

这样,在添加每个函数的时候,只需要写针对特定参数的逻辑,调用getTotalPrice的时候,自动根据参数长度实际调用不同的函数。

很容易想到要对不同的函数进行缓存,同时为了公用同一个函数名,缓存的函数需要匿名,进而联想到闭包可以保存局部变量的引用的特性,以下是addFunction的实现:

function addFunction(object, funcName, fn) {
    var oldFunc = object[funcName];
    object[funcName] = function() {
        return (fn.length === arguments.length ? fn : oldFunc).apply(this, arguments);
    }
}

addFunction方法的作用域中,保存了原方法的引用,通过对参数长度的比较确定最终执行哪个匿名函数,要注意的是一个函数的length属性表示改函数接受的形参数量,而arguments.length表示实际传入的参数数量。匿名函数访问oldFuncfn则是典型的闭包的应用,并没有把函数存储在任何典型的数据结构中。

addFunction(methods, "getTotalPrice", function(total) {
    console.log(total);
});
addFunction(methods, "getTotalPrice", function(total, discount) {
    console.log(total * discount);
});

methods.getTotalPrice(20); // 输出20
methods.getTotalPrice(20, 0.8); // 输出16

要注意的是,这种方式只能针对不同数量的参数,不能判断参数的名称或类型,如果要判断的话,势必会牺牲addFunction方法的通用性。另外,每添加一个函数,就会增加一层嵌套,调用深度过深的话性能开销也会比较大,使用的时候要进行权衡。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86140.html

相关文章

  • 机器学习01 - Regression 案例学习 (上)

    摘要:我们就有了组训练数据我们将其进化前的值和进化后的值画在一个二维坐标图上横轴为进化前的值,那每个蓝色的点都代表一只宝可梦现在我们有了和,但是我们还需要一个函数来将它们连接起来,这个函数就是接下来要讲的第三步中间蓝色的块就是误差函数。 前言 如果遇到排版问题,请点击 阅读原文 这个课程是来自于 YouTube 上 NTU 李宏毅老师的视频课程,老师的课讲得非常有趣,通过引入 Pokémon...

    wean 评论0 收藏0
  • 友盟+CEO朋新宇:DI进化,是选择更是态度

    摘要:友盟朋新宇在开场演讲中,友盟朋新宇表示,在数据化智能化的今天,进化是一种态度,更是一种选择。在朋新宇看来,数据加工有三大过程过程第一层是采集,友盟技术平台每天能够支撑万亿级的采集能力。 10月16日,友盟+主办的2018UBDC全域大数据峰会在北京举办。峰会以DI·进化为主题——8小时,10余家黑科技企业,超40位国内顶级专家主题分享,近3500位数据从业者共同见证,旨在让更多企业会用...

    Cympros 评论0 收藏0
  • 生成器进化到协程 Part 1

    摘要:生成器用于定义生成器函数只要存在该函数必定是一个生成器调用该函数返回一个生成器让一个生成器前进使用使一个生成器前进到下一个语句处,并将产出值作为其返回值。 前言 这篇文章大部分来自 David Beazley 在 PyCon 2014 的 PPT 《Generators: The Final Frontier》。这个PPT很长而且非常烧脑,建议在阅读前应了解 Python 的生成器与携...

    lemon 评论0 收藏0
  • 利用遗传算法优化神经网络:Uber提出深度学习训练新方式

    摘要:和的得分均未超过右遗传算法在也表现得很好。深度遗传算法成功演化了有着万自由参数的网络,这是通过一个传统的进化算法演化的较大的神经网络。 Uber 涉及领域广泛,其中许多领域都可以利用机器学习改进其运作。开发包括神经进化在内的各种有力的学习方法将帮助 Uber 发展更安全、更可靠的运输方案。遗传算法——训练深度学习网络的有力竞争者我们惊讶地发现,通过使用我们发明的一种新技术来高效演化 DNN,...

    AlienZHOU 评论0 收藏0

发表评论

0条评论

alin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<