“添加"与链接/参数的不同组合一起使用的函数 [英] "add" function that works with different combinations of chaining/arguments

查看:40
本文介绍了“添加"与链接/参数的不同组合一起使用的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个在许多情况下都可以使用的add函数.

I'm trying to write an add function that will work in many scenarios.

add(2,2,2) //6
add(2,2,2,2) //8
add(2)(2)(2) // 6
add(2)(2)(2,2).value() //8
add(2,2)(2) + 2 //8
add(2).add(2) //4
add(2,2,2).add(2).add(2,2).value() //12
add(2,2,2).add(2).value() //8

这是我到目前为止所拥有的:

This is what I have so far:

function add(){
    var sum = 0;
    for( var i in arguments ){
        sum += arguments[i];
    }

    var ret = add.bind(null, sum);

    ret.value = function () {
      return sum;
    }

    ret.add = function () {
      for( var i in arguments ){
        sum += arguments[i];
      }
      return sum;
    }

    ret.valueOf = function(){ return sum; };
    
    return ret;
}

console.log(add(2,2,2));
console.log(add(2,2,2,2));
console.log(add(2)(2)(2));
console.log(add(2)(2)(2,2).value());
console.log(add(2,2)(2) + 2);
console.log(add(2).add(2));
console.log(add(2,2,2).add(2).value());
console.log(add(2,2,2).add(2).add(2,2).value());

我在最后两种情况下有问题:

I am having a problem with the last two cases:

  add(2,2,2).add(2).add(2,2).value() //12
  add(2,2,2).add(2).value() //8

如果我想将两个以上的函数链接在一起,并且还要将value函数添加到每个函数中,我似乎必须继续嵌套add函数,但是显然我缺少一些简单的方法来允许我将它们链接在一起尽我所能,并在其中任何一个上赋予价值.

It seems like I would have to keep nesting the add functions if I wanted to chain more than two together and also add the value function to each of them, but obviously I'm missing something simple that will allow me to chain them as much as I like, and call value on any of them.

还需要始终返回整数(而不是字符串),似乎有时它们会返回,而有时则不?

Also they need to always return ints (not strings), and it seems like sometimes they do and other times they don't?

推荐答案

在两个不同的地方以类似的方式使用arguments的方式,很明显,您正在复制功能,这就是为什么要运行不得不无限嵌套" .value()方法来解决这个问题.

Looking at the way you're using arguments in similar ways in two different places, it's clear that you are duplicating functionality and that is why you are running into this problem with having to "infinitely nest" the .value() method.

要认识的关键是add()可以返回一个将自身引用为自己的add属性的函数.这将使add(1,2)(3)的行为与add(1,2).add(3)完全相同.可以这样完成:

The key thing to recognize is that add() can return a function that references itself as its own add property. This will allow add(1,2)(3) to behave exactly the same as add(1,2).add(3). This can be done like so:

function add() {
  var sum = Array.prototype.reduce.call(arguments, function(l, r) {
    return l + r;
  }, 0);

  var ret = add.bind(null, sum);
  ret.add = ret;

  ret.value = ret.valueOf = Number.prototype.valueOf.bind(sum);      
  ret.toString = Number.prototype.toString.bind(sum);

  return ret;
}

snippet.log(add(2,2,2));
snippet.log(add(2,2,2,2));
snippet.log(add(2)(2)(2));
snippet.log(add(2)(2)(2,2).value());
snippet.log(add(2,2)(2) + 2);
snippet.log(add(2).add(2));
snippet.log(add(2,2,2).add(2).value());
snippet.log(add(2,2,2).add(2).add(2,2).value());

snippet.log(add(1, 2, 3)(4, 5).add(6, 7)(8).add(9, 10));
snippet.log(add(5,4)(3).add(2)(1) * 10);

<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

上述方法仍然存在两个潜在问题,一个是未成年人,另一个是未成年人.

There are still two potential issues with the above approach, one minor and one a little less minor:

  • 每次使用add函数时(包括在链接过程中),都会重新执行属性引用和函数定义
  • 如果有人覆盖了add标识符,则将导致整个实现中断:
  • There are property references and function definitions that are re-executed every time the add function is used (including during chaining)
  • If someone overwrites the add identifier, it would cause the whole implementation to break:

function add() {
  var sum = Array.prototype.reduce.call(arguments, function(l, r) {
    return l + r;
  }, 0);

  var ret = add.bind(null, sum);
  ret.add = ret;

  ret.value = ret.valueOf = Number.prototype.valueOf.bind(sum);
  ret.toString = Number.prototype.toString.bind(sum);

  return ret;
}

var myAdd = add;
add = "boom!";
myAdd(1, 2, 3); // TypeError: add.bind is not a function

这两种方法都可以通过IIFE进行补救:

Both of these can be remedied with an IIFE:

var add = (function () {
    var reduce = Array.prototype.reduce,
        np = Number.prototype,
        valueOf = np.valueOf,
        toString = np.toString,
        plus = function (l, r) { return l + r; };

    return function add() {
        var sum = reduce.call(arguments, plus, 0);

        var ret = add.bind(null, sum);
        ret.add = ret;

        ret.value = ret.valueOf = valueOf.bind(sum);      
        ret.toString = toString.bind(sum);

        return ret;
    }
})();

var myAdd = add;
add = "U Can't Touch This";   // hammertime

snippet.log(myAdd(1, 2, 3)(4, 5).add(6, 7)(8).add(9, 10));
snippet.log(myAdd(5,4)(3).add(2)(1) * 10);

<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

这篇关于“添加"与链接/参数的不同组合一起使用的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆