js中实现单分派泛函数

栏目: JavaScript · 发布时间: 7年前

内容简介:有这样一个函数,我们根据传入的第一个参数类型不同,以不同方式执行相同操作(单分派泛函数), 我们来看一个简单的例子:这个例子比较简单,每一个我们先来看看使用方式:

有这样一个函数,我们根据传入的第一个参数类型不同,以不同方式执行相同操作(单分派泛函数), 我们来看一个简单的例子:

function show(value) {
    if(value instanceof Array) {
        console.log(value.join('-'));
    } else if(value instanceof Date) {
        console.log(value * 1);
    } else if (value instanceof Number || value instanceof Boolean) {
        console.log(value * value)
    } else {
        console.log(value);
    }
}
复制代码

这个例子比较简单,每一个 if 后面只有一行代码,然而在实际工作中,也许每一个 if 后面都有一段逻辑复杂逻辑复杂的代码,我们通常的处理方式就是将其拆分出来作为一个新的函数,然后在 if 里面调用,现在我向大家介绍一种新的方法来出来这种情况。

我们先来看看使用方式:

const show = singledispatch(vlaue => console.log(value));
show
    .dispatch(value => console.log(value * value))
    .register(Number)
    .register(Boolean);
    .dispatch(value => console.log(value * 1))
    .register(Date);
    .dispatch(value => console.log(value.join('-')))
    .register(Array);

show(2); // 4
show(true); // 1
show([3, 4, 5]) // 3-4-5
show(new Date()) // 1542177163659
show({a: 1}) // [object Object] 
复制代码

singledispatch 接受一个函数,返回一个函数对象 showshow 先dispatch一个函数,之后注册一个Number和Boolean,表示 show 传入的参数如果是数字或者布尔类型,就调用dispatch的这个函数,之后也是这样。

singledispatch 需要返回一个函数对象,我们假设叫 out ,这个函数对象有两个方法分别为 dispatchregister ,链式调用就需要返回 out ;具体实现过程如下,

function singledispatch(fn /* 默认是一个空函数*/ = Function.prototype) {
    let current; // 用于记录啊dispatch的函数
    let registry = {}; // 一个对象,用于存储某个类型下对应调用的函数
    function out(arg){
        let type = Object.prototype.toString.call(arg);
        if(registry[type]) {
            return registry[type](arg);
        } else {
            return fn(arg);
        }
    }

    out.dispatch = function dispatch(f) {
        if(typeof f !== 'function') {
            throw Error('some error')
        }
        current = f;
        return out;
    }

    out.register = function register(ctor) {
        if(!current) {
            throw Error('register必须在dispatch之后调用')
        }
        registry[`[object ${ctor.name}]`] = current;
        return out
    }

    return out;
}
复制代码

有的时候,我们并不是根据类型做判断,我们希望可以自定义的方式去判断,因此,register可以传入一个函数,用这个函数去做判断,就像下面这个样子:

const f = singledispatch();

f
    .dispatch(v => v * v * v).register(v => v > 10)
    .dispatch(v => v * v).register(v => v <= 10);

f(11) // 1331
f(5) // 25

复制代码

此时的 singledispatch 需要修改 registerout

function singledispatch(fn = Function.prototype) {
    let current;
    let registry = [];
    let conditions = []
    function out(arg){
        let index = conditions.findIndex(f => f(arg));
        if(index >= 0) {
            return registry[index](arg);
        } else {
            return fn(arg);
        }
    }

    out.dispatch = function dispatch(f) {
        if(typeof f !== 'function') {
            throw Error('some error')
        }
        current = f;
        return out;
    }

    out.register = function register(condition) {
        if(!current) {
            throw Error('register必须在dispatch之后调用')
        }
        if(typeof condition !== 'function') {
            throw Error('some error')
        }
        conditions.push(condition);
        registry.push(current);
        return out
    }

    return out;
}
复制代码

以上所述就是小编给大家介绍的《js中实现单分派泛函数》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Blockchain Basics

Blockchain Basics

Daniel Drescher / Apress / 2017-3-16 / USD 20.99

In 25 concise steps, you will learn the basics of blockchain technology. No mathematical formulas, program code, or computer science jargon are used. No previous knowledge in computer science, mathema......一起来看看 《Blockchain Basics》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具