如何链接js函数?

时间:2017-09-21 07:54:44

标签: javascript ecmascript-6

让图像我有一个数字,我想执行一些算术运算示例。

x.add(3).subtract(2).print() // result 1

或者

0.add(3).subtract(2).print() // result 1 (I have no code for this)

目前我正在尝试以下代码。我想知道是否有更简洁的方法来实现相同的结果,

由于



var test = function () {

    var i = 0;

    var add = function (j) {
        i += j;
        return this;
      };

    var subtract = function (j) {
        i -= j;
        return this;
      };

    var print = function () {
        console.log(i);
      };

    return {
        add: add,
        subtract: subtract,
        print: print
    };
  };

var x = test();

x.add(3).subtract(2).print();




3 个答案:

答案 0 :(得分:4)

这个问题几乎有两个独立的答案:

  • 超常规答案。

  • 适用于对象的一般答案,呃,一般。

  • 适用于数字的具体答案。

超常规答案

你可以在早期函数返回一个对象(或者可以被隐式强制转换为对象的东西)的任何时候链接函数,该对象具有另一个函数作为属性(松散地,“方法”)。例如,您可以在.toString().toUpperCase()上链接Date

var dt = new Date();
console.log(dt.toString().toUpperCase();

...因为Date.prototype.toString返回一个字符串,字符串有一个toUpperCase方法。

适用于对象的一般答案,呃,一般

一种常见且有用的模式是拥有一个对象,该对象的方法返回对同一对象或同一“类型”的另一个对象的引用。 (有时人们会说“形状”而不是“类型”,因为JavaScript在很大程度上是无类型的。)例如,jQuery使用它可以产生很好的效果。 $()返回一个jQuery对象;根据您调用它的方法,您将获得相同的jQuery对象(例如,each)或表示操作结果的新jQuery对象(例如,find) 。这种模式非常有用,包括可变对象,尤其是不可变对象。

要在您自己的对象中执行此操作:仅返回return this相同的对象。要返回具有相同“形状”的新对象,您将使用用于对象的任何构造机制来创建要返回的新对象。

例如,如果我们在序列的开头添加一个创建“流式”数字的函数,我们要么让它变为可变并且每次都返回this

function nstream(val) {
  return {
    // Our add operation returns this same instance
    add: function(n) {
      val += n;
      return this;
    },
    // Same with multiply
    multiply: function(n) {
      val *= n;
      return this;
    },
    // To access the underlying value, we need an accessor
    result: function() {
      return val;
    },
    // This provides compatibility with built-in operations
    // such as + and *
    valueOf: function() {
      return val;
    }
  };
};
// Using only nstream ops:
console.log(nstream(1).add(3).multiply(4).result());
// Implicitly using valueOf at the end:
console.log(nstream(1).add(3) * 4);

或者我们可以使nstream成为不可变的,其中每个操作都返回一个新的nstream

function nstream(val) {
  return {
    add: function(n) {
      return nstream(val + n);
    },
    // Same with multiply
    multiply: function(n) {
      return nstream(val * n);
    },
    // To access the underlying value, we need an accessor
    result: function() {
      return val;
    },
    // This provides compatibility with built-in operations
    // such as + and *
    valueOf: function() {
      return val;
    }
  };
};
// Using only nstream ops:
console.log(nstream(1).add(3).multiply(4).result());
// Implicitly using valueOf at the end:
console.log(nstream(1).add(3) * 4);

矛盾的是,像这样的不可变对象可以增加减少代码中的内存压力,具体取决于它们是否可以帮助您避免防御性副本。例如,如果nstream是另一个对象的成员并且您想知道它不能改变,如果它是可变的,那么在将其交给其他代码时,您必须制作一个防御性副本;如果它是不可变的,你不必,但你必须在“修改”它时创建副本。但是,不可变对象的成本和收益是有点问题的。 : - )

适用于号码的具体答案

当您尝试在某个数字上调用方法时,您必须将该方法添加到Number.prototype。然后你有你的方法(addmultiply等)返回操作的结果,这是一个数字将有你的其他方法。这是一个简单的例子:

Object.defineProperties(Number.prototype, {
  add: {
    value: function(n) {
      return this + n;
    }
  },
  multiply: {
    value: function(n) {
      return this * n;
    }
  }
});
console.log(1..add(3).multiply(4));

关于这一点的几点说明:

  • 一如既往在扩展内置原型时,使用Object.definePropertyObject.defineProperties而不使用enumerable: true非常重要,因此新属性不可枚举。 (虽然有数字但这并不是什么大问题。对于数组来说更是如此。而且我们完全保留普通对象[例如,Object.prototype]。)
  • ..中的1..add(3)可能看起来很奇怪,但它是您在数字文字上调用方法的两种方法之一。第一个.是小数点。第二个.是属性访问者运算符。另一种方式是(1).add(3)因为数字文字结束时没有混淆。显然,这并没有提出变量:var n = 1; console.log(n.add(3).multiply(4));工作得很好。
  • 在那里进行数字对象和数字基元之间有一些相关的转换:当你访问基元(数字,字符串,布尔值)上的属性(包括函数属性)时,JavaScript引擎强制转换原语到其等效的对象类型(Number,String,Boolean),然后在该对象上查找属性。由于它是一个新创建的对象,它唯一的属性来自它的原型。因此1..add(3)创建一个新的Number对象,然后在该对象上调用add。当我们执行addreturn this + n内,+会将对象强制回原始值。当然,所有这些都在可能的情况下进行了优化,并且在JavaScript引擎的重要位置。

答案 1 :(得分:0)

您可以向Number对象添加一些原型,并使用浮点和点的方法调用该值。

不建议更改标准对象的标准,因为它们可能会导致对代码的误解。

Number.prototype.add = function (v) { return this + v; };
Number.prototype.multiply = function (v) { return this * v; };

console.log(1..add(2).multiply(4)); // 12

答案 2 :(得分:0)

只要返回上一个方法,就可以链接方法。 所以,在这种情况下,你需要创建一个"类" thas拥有所有需要的方法,然后返回一个"实例"所有这些课程中的那一课。

var myNum = function(n) {

  var num = n;

  this.add = function(a) {

   var b = n+a;
   return new myNum(b) ;

  } 

}