6

问题在标题,但首先请看这段代码:

function number(a) {
    return {
        add: function(b) {
            result = a + b;
            return this;
        }, substract(b) {
            result = a - b;
            return this;
        }
}

上面的这些代码是链式规则的简单示例。我重新调整一个对象,以便我可以连续执行它:

number(2).add(5).add(3 * 12).substract(Math.random());

我的问题是,我必须重新调整一个对象以保持函数可链接。我想模仿链式规则,但要返回特定的值。例如number(2).add(3)将返回 5。

任何建议都受到高度赞赏。

先谢谢大家了。[X]

4

3 回答 3

6

使像 5 这样的数值“可链接”的一种方法是在适当的原型对象上定义一个方法,例如Number.prototype. 例如:

Number.prototype.add = function (n) {
   return this + n
}

(5).add(2) // 7
5.0.add(2) // 7
5..add(2)  // 7
((5).add(2) + 1).add(34) // okay! 42

上面的语法很有趣,因为5.add(2)它是无效的:JavaScript 在5.. 因为这是一个全局副作用(它将影响所有数字),所以应注意避免意外的交互。

唯一的另一个使“5”可链接的另一种方法是创建一个新Number对象(5 不是真正的 Number 实例,即使它使用 Number.prototype!)然后复制所需的方法。(我曾经认为这是唯一的另一种方式,但请参阅 KooiInc 的回答——但是,我不确定返回非字符串的定义有多明确toString。)

function ops(a) {
  return {
    add: function(b) {
      var res = new Number(a + b) // important!
      var op = ops(res)
      res.add = op.add // copy over singletons
      return res
    }
  }
}
function number(a) {
  return ops(a)
}

number(5).add(2) + 1           // 8
(number(5).add(2) + 1).add(34) // error! add is not a function

但是,请记住,这会带来一些微妙的问题:

typeof 5                        // number
typeof new Number(5)            // object
5 instanceof Number             // false
new Number(5) instanceof Number // true

这就是为什么我们需要一个Number(在 JavaScript 中搜索“primitives”):

x = 5
x.foo = "bar"
x.foo // undefined

此外,结合 cwolves 的回答,请考虑:

function number (n) { 
  if (this === window) { // or perhaps !(this instanceof number)
    return new number(n)
  } else {
    this.value = n
  }
}

然后两者new number(2)number(2)将评估为一个的数字对象。

number(2).value     // 2
new number(2).value // 2
number(2) instanceof number     // true
new number(2) instanceof number // true

快乐编码。

于 2011-06-26T07:07:06.837 回答
3

你有两个选择。您可以返回新对象:

function number(a){
    return this instanceof number ? (this.value = a, this) : new number(a);
}

number.prototype = {
    valueOf : function(){
        return this.value;
    },
    add : function(b){
        return new number(this.val + b);
    },
    subtract : function(b){
        return new number(this.val - b);
    }
};

或者您可以修改现有的(与上面的代码大部分相同,这是不同的):

add : function(b){
    this.value += b;
    return this;
},

不同之处在于它们的行为方式:

var x = new number(5),
    y = x.add(10);

// with first example
// x == 5, y == 15


// with 2nd example
// x == 15, y == 15, x === y
于 2011-06-26T05:36:07.323 回答
3

如果将值定义为属性 ( this.a) 并toString在返回的 Object 中使用,则可以链接方法:

function number(a) {
    return {
        a: Number(a) || 0, //if not a, or a===NaN, default = 0
        add: function(b) {
            this.a += b;
            return this;
        },
        subtract: function(b){
            this.a -= b;
            return this;
        },
        valueOf: function(){
          return Number(this.a);
        },
        toString: this.valueOf
    }
}

var n = number(5);
alert(number.add(5).add(2).subtract(2)); //=> 10
alert(number.add(0.5));                  //=> 10.5
alert(number(2).add(5).add(3 * 12).subtract(Math.random());
                                         //=> 42.36072297706966
于 2011-06-26T08:39:20.410 回答