如何在不使用原型的情况下链接函数?

发布于 2025-01-06 23:15:26 字数 298 浏览 4 评论 0原文

我有很多我一生中收集的有用的功能。

function one(num){
    return num+1;
}

function two(num){
    return num+2;
}

我可以使用 two(two(one(5))) 调用它们,

但我更喜欢使用 (5).one().two().two()

在不使用原型的情况下如何实现这一目标?

我试图了解下划线链是如何工作的,但他们的代码太密集,无法理解它

I have a bunch of useful functions that I have collected during my whole life.

function one(num){
    return num+1;
}

function two(num){
    return num+2;
}

I can call them with two(two(one(5)))

But I would prefer to use (5).one().two().two()

How can I achieve this without using prototype?

I tried to see how underscore chain works, but their code is too intense to understand it

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一页 2025-01-13 23:15:26

点语法是为对象保留的。因此,您可以执行类似的操作

function MyNumber(n) {
    var internal = Number(n);
    this.one = function() {
        internal += 1;
        // here comes the magic that allows chaining:
        return this;
    }
    // this.two analogous
    this.valueOf = function() {
        return internal;
    }
}

new MyNumber(5).one().two().two().valueOf(); // 10

,或者您将在本机 Number 对象/函数的原型上实现这些方法。这将允许 (5).one()...

The dot syntax is reserved for objects. So you can do something like

function MyNumber(n) {
    var internal = Number(n);
    this.one = function() {
        internal += 1;
        // here comes the magic that allows chaining:
        return this;
    }
    // this.two analogous
    this.valueOf = function() {
        return internal;
    }
}

new MyNumber(5).one().two().two().valueOf(); // 10

Or you're going to implement these methods on the prototype of the native Number object/function. That would allow (5).one()...

薄荷港 2025-01-13 23:15:26

为了避免像 @Bergi 的解决方案那样在链的末尾调用 toValue ,您可以使用带有附加方法的函数。当尝试将其转换为原始类型时,JS 会自动调用 toValue

function MyNumber(n) {
    function x () { }
    x.one = function() { n++; return this; };
    x.valueOf = function() { return n; };
    return x;
}

然后,

MyNumber(5).one().one()
> 7

In order to avoid having to call toValue at the end of the chain as in @Bergi's solution, you can use a function with attached methods. JS will call toValue automatically when trying to convert to it a primitive type.

function MyNumber(n) {
    function x () { }
    x.one = function() { n++; return this; };
    x.valueOf = function() { return n; };
    return x;
}

Then,

MyNumber(5).one().one()
> 7
小红帽 2025-01-13 23:15:26

一个不错的通用替代方法是创建一个自定义函数组合函数,

var go = function(x, fs){
   for(var i=0; i < fs.length; i++){
       x = fs[i](x);
   }
   return x;
}

您可以这样称呼它:

go(5, [one, two, two])

我个人不太喜欢方法链接,因为它限制您使用一组预定义的函数,并且内部值之间存在某种阻抗不匹配。 “链接对象”和外部的自由值。

A nice and general alternative is creating a custom function composition function

var go = function(x, fs){
   for(var i=0; i < fs.length; i++){
       x = fs[i](x);
   }
   return x;
}

You can call it like this:

go(5, [one, two, two])

I am personaly not a big fan of method chaining since it restricts you to a predefined set of functions and there is kind of an impedance mismatch between values inside the "chaining object" and free values outside.

§普罗旺斯的薰衣草 2025-01-13 23:15:26

另一种选择是使用 lodash flow 函数。例如:

var five = _.flow(one, two, two)
five(5)

我更喜欢将新链分配给变量。它给它一个清晰的名称并鼓励重复使用。

顺便说一句,lodash 还有助于将附加参数传递给链的函数。例如:

var addFive = _.flow(
   _.partialRight(_.add, 1),
   _.partialRight(_.add, 2),
   _.partialRight(_.add, 2)
)

还有许多其他有用的函数可以帮助进行功能链接,例如,partialspreadflipnegate 等

Another alternative is to use lodash flow function. For example:

var five = _.flow(one, two, two)
five(5)

I prefer assigning a new chain to a variable. It gives it a clear name and encourages re-use.

Btw, lodash also helps in passing additional arguments to the functions of the chain. For example:

var addFive = _.flow(
   _.partialRight(_.add, 1),
   _.partialRight(_.add, 2),
   _.partialRight(_.add, 2)
)

There are many other useful functions to help in functional chaining, e.g., partial, spread, flip, negate, etc.

GRAY°灰色天空 2025-01-13 23:15:26

JS中基本上没有函数组合。即使有,也会与您在问题中提到的顺序相反。即<代码>两个。二 。 one 因为 Math 是这样声明组合运算符的。您想要的顺序称为管道。

话虽如此,如果您确实想要使用点运算符进行组合,您仍然可以通过 Proxy 对象重载 . 运算符来实现。这是一个稍微复杂的主题,您可以查看 这个不错的博客文章 获取一些想法。

然而,满足您的需求的最简单方法是将函数数组减少为:

var pipe = (fs,x,y) => fs.reduce((r,f) => f(r),{x,y}),
    fs   = [ ({x,y}) => ( x++
                        , y++
                        , {x,y}
                        )
           , ({x,y}) => ( x*=3
                        , y*=3
                        ,{x,y}
                        )
           , ({x,y}) => ( x--
                        , y--
                        , {x,y}
                        )
           ];

var {x,y} = pipe(fs,1,2);
console.log(x,y);

Basically there is no function composition in JS. Even if there had been, it would be in the reverse order of what you mention in your question. ie two . two . one because Math declares composition operator like that. The order you want is called piping.

Having said that if you really want composition with dot operator, you may still do it by overloading the . operator via the Proxy object. It's a slightly convoluted topic and you may check this nice blogpost for some ideas.

However the simplest approach for your need would be by reducing an array of functions as;

var pipe = (fs,x,y) => fs.reduce((r,f) => f(r),{x,y}),
    fs   = [ ({x,y}) => ( x++
                        , y++
                        , {x,y}
                        )
           , ({x,y}) => ( x*=3
                        , y*=3
                        ,{x,y}
                        )
           , ({x,y}) => ( x--
                        , y--
                        , {x,y}
                        )
           ];

var {x,y} = pipe(fs,1,2);
console.log(x,y);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文