在库中实现Javascript链接的最佳方法

在库中实现Javascript链接的最佳方法,javascript,chaining,Javascript,Chaining,我正在创建一个JavaScript库。我一直在尝试实现链接 0:我第一次想到的是: function V(p) { return { add : function(addend) { return V(p + addend); }, sub : function(subtra) { return V(p - subtra); }, }; } 使用此方法,我可以轻松地链接: V(3).add(7).sub(5) // V(5) 不幸的是,结果总是一个包装的V()函数,我

我正在创建一个JavaScript库。我一直在尝试实现链接

0:我第一次想到的是:

function V(p) {
  return {
    add : function(addend) { return V(p + addend); },
    sub : function(subtra) { return V(p - subtra); },
  };
}
使用此方法,我可以轻松地链接:

V(3).add(7).sub(5) // V(5)
不幸的是,结果总是一个包装的V()函数,我无法以这种方式提取结果值。所以我考虑了一下这个问题,想出了两个半解

1:将标志传递给最后一个方法

function V(p, flag) {
  if(flag)
    return p;
  else
    return {
      add : function(addend, flag) { return V(p + addend, flag); },
      sub : function(subtra, flag) { return V(p - subtra, flag); }
    };
}
使用此方法,我可以通过向我使用的最后一个方法传递标志来结束链:

V(3).add(7).sub(5, true) // 5
虽然这工作得很好,但它需要一些代码重复,使链接不那么可读,我的代码也不那么优雅

2:使用start()和end()方法

_chain = false;
function V(p) {
  function Wrap(w) {
    return (_chain) ? V(w) : w;
  }
  return {
    add : function(addend) { return Wrap(p + addend); },
    sub : function(subtra) { return Wrap(p - subtra); },
    start : function() { _chain = true; },
    end : function() { _chain = false; return p; }
  };
}
使用此方法,您可以不使用更多代码执行单个操作:

V(3).add(7) // 10
但链接需要另外两种方法,这使得内容的可读性大大降低:

V(3).start().add(7).sub(5).end() // 5
所以基本上我只是在寻找实现链接到我的库的最佳方法。理想情况下,我正在寻找一些我可以使用任何数量的方法,而不需要以不雅的方式终止链的东西

V(3).add(7).sub(5) // 5, perfect chaining
为什么不引入一个私有变量并进行研究呢?我想那更方便。另外,最好有一个纯“getter”,它最终返回计算值。这可能看起来像:

function V(p) {
    var value = p;

    return {
        add : function(addend) { value += addend; return this; },
        sub : function(subtra) { value -= subtra; return this; },
        get : function() { return value; }
    };
}

V(5).add(7).sub(5).get();  // 5

显然,在getter函数中不能返回
对象。因此,您需要一些方法,其中链接结束并返回一个值。

在某些情况下,它确实需要类似于
end
,但在简单的算术示例中,它不需要

function V(initial_val){
  if(!(this instanceof V)){
    return new V(initial_val);
  }

  var num = initial_val || 0;

  this.set = function(val){
    num = val;
    return this;
  }
  this.add = function(val){
    num += val;
    return this;
  }
  this.sub = function(val){
    num -= val;
    return this;
  }
  this.valueOf = function(){
    return num;
  }
  this.toString = function(){
    return ""+num;
  }
}
通过向对象添加
valueOf
toString
函数,可以访问其原语值。也就是说,您可以执行以下操作:

var num = V(0).add(1).sub(2), another_num = 3 + num; // num = -1 and another_num = 2;

我将对浩池的优秀回答作如下修改:

如果您有许多V对象和 在toString函数中,我调用通用数字toString 你愿意给出的论点

function V (n) {
  if (!(this instanceof V)) {
    return new V (n);
  }

  this.num = +n || 0;
  return this;
}

V.prototype = {
  set: function (val) {
    this.num = val;
    return this;
  },
  add: function (val) {
    this.num += val;
    return this;
  },
  sub: function (val) {
    this.num -= val;
    return this;
  },
  valueOf: function () {
    return this.num;
  },
  toString: function () {
    return this.num.toString.apply (this.num, arguments);
  }
}

嗯,我想那会有用的。这绝对是迄今为止我见过的最好的提案。我认为这实际上不起作用。您设置的是p而不是值。这应该会回来7@nathan冈萨雷斯:我的错,修正了错别字。冷静点,我没有抄袭你的答案,我只是自己想出了同样的解决方案。我删除了我的答案。我建议看看jQuery实现链接的方式。你会发现
下划线.js