【问题标题】:Chain custom javascript functions链接自定义 javascript 函数
【发布时间】:2016-01-27 00:23:48
【问题描述】:

搜索了很长一段时间后,我仍然没有找到我要找的东西。

有相当多的示例需要创建新实例,或者只有不返回任何内容的函数(这意味着可以通过返回 this 来解决问题)。

我希望下面的例子能很好地说明我的观点:

// Say I have these functions
function aNumber(){
    var max = 100, min = 0;
    return (Math.floor(Math.random() * (max - min + 1)) + min);
}
function divideBy(_number, _divider){
    return (_number / _divider);
}
function multiplyBy(_number, _multi){
    return (_number * _multi);
}
function add(_number, _add){
    return (_number + _add);
}
function subtract(_number, _sub){
    return (_number - _sub);
}

// #########################################################

// I can do this with them
var test = aNumber();
test = divideBy(aNumber, 2);
test = add(aNumber, 5);
test = multiplyBy(aNumber, 3);
test = subtract(aNumber, 10);

// I would like to do this however:
var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10);

使最后一行工作的最有效方法是什么?

我是不是误会了,如果不创建某个东西的新实例就可以做到这一点?

【问题讨论】:

标签: javascript chaining


【解决方案1】:

是的,这需要更改 ObjectPrototype。对象是实例。所以你需要创建一个对象来做这种事情。

function MyNum(value) {
  this._val = value;      // Having _variable is for denoting it is a private variable.
}

使用以下方法初始化对象:

var myNum = new MyNum(5);

现在使用这个,定义这些:

MyNum.prototype.divideBy = function () {}
MyNum.prototype.multiplyBy = function () {}

不要忘记在这些函数中使用return this;

【讨论】:

  • 你的意思可能是不要忘记return this;,为了可链接性?
【解决方案2】:

在没有实例和原型关键字的情况下尝试如下创建。

这里增加了一种方法,您可以默认设置数字或随机数。如果没有指定数字。

  var Calculator = {

setNumber: function(givenNumber) {
  var max = 100,
      min = 0;

  this.number = (givenNumber) ? givenNumber : (Math.floor(Math.random() * (max - min + 1)) + min);
  return this;
},

divideBy: function(_divider) {
  this.number = (this.number / _divider);
  return this;
},

multiplyBy: function(_multi) {
  this.number = (this.number * _multi);
  return this;
},

add: function(_add) {
  this.number = (this.number + _add);
  return this;
},

subtract: function(_sub) {
  this.number = (this.number - _sub);
  return this;
},

result: function () {
  return this.number;
}
  }

  document.write('<pre>');
  document.writeln(Calculator.setNumber(2).divideBy(2).add(5).multiplyBy(3).subtract(10).result());
  document.writeln(Calculator.setNumber(4).divideBy(2).add(5).multiplyBy(3).subtract(10).number);
  document.writeln(Calculator.setNumber().divideBy(2).add(5).multiplyBy(3).subtract(10).result());
  document.write('</pre>');

【讨论】:

  • 我会使用.result() 而不是.number
  • 这种单例设计不允许多个并发计算。
  • 您的意思是说,我们必须使用实例化方法是一种很好的方法,但它确实有效。运行代码 sn -p
【解决方案3】:

是的,您确实需要创建一些东西的实例。这可以是简单的对象字面量、函数构造函数等...

这个想法是你所有的方法都存储在某个对象上,对吧?访问这些方法的唯一方法是通过该对象访问它们。考虑到这一点,每个函数都必须返回包含所有这些方法的对象。

一个简单的例子

var myMethods = {
  one: function() {
    console.log('one');
    // You can return 'this' or reference the object by name
    return this;
    // or 
    // return myMethods;
  },

  two: function() {
    console.log('two');
    return this;
  }
};

myMethods.one().two().one().two();
//=> 'one', 'two', 'one', 'two'

当你直接引用方法时要小心,像这样

var someMethod = myMethods.one;
someMethod() //=> undefined

这是因为 'this' 现在正在引用全局对象,这是另一回事了。请注意您是否以这种方式引用方法。

【讨论】:

    【解决方案4】:

    虽然一般不建议在 JavaScript 原语的原型中添加函数,但是你可以通过这样做来做你想要的。

    function aNumber(){
        var max = 100, min = 0;
        return (Math.floor(Math.random() * (max - min + 1)) + min);
    }
    
    function divideBy(_number, _divider){
        return (_number / _divider);
    }
    function multiplyBy(_number, _multi){
        return (_number * _multi);
    }
    function add(_number, _add){
        return (_number + _add);
    }
    function subtract(_number, _sub){
        return (_number - _sub);
    }
    
    Number.prototype.divideBy = function(_divider){
    	return divideBy(this, _divider);
    };
    
    Number.prototype.multiplyBy = function(_multi){
    	return multiplyBy(this, _multi);
    };
    
    Number.prototype.add = function(_add){
    	return add(this, _add);
    };
    
    Number.prototype.subtract = function(_sub){
    	return subtract(this, _sub);
    };
    
    var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10);

    【讨论】:

    • 那些额外的功能看起来像很多样板绒毛。为什么不把逻辑放在方法中?
    • 你可以,但我的目的是展示一种适用于 OP 列出的两种方法的方法。您会看到我从原始帖子中的内容开始,然后只是将函数添加到原始类型。如果你想以不止一种方式使用一个函数,那么只引用一个完成工作的函数会更干。
    【解决方案5】:

    就像 Praveen 和 Venkatraman 说的,我发现了以下关于链接的帖子,但是在访问任何更改方法之前都必须声明一个新实例 method-chaining-in-javascriptbeautiful-javascript-easily-create-chainable-cascading-methods-for-expressiveness

    或者你可以使用这个实现https://jsfiddle.net/ayinloya/zkys5dk6/

    function aNumber() {
      var max = 100;
      var min = 0;
      this._number = (Math.floor(Math.random() * (max - min + 1)) + min);
      console.log("a init", this._number)
    }
    
    aNumber.prototype.divideBy = function(_divider) {
      this._number = (this._number / _divider)
      return this;
    }
    
    aNumber.prototype.multiplyBy = function(_multi) {
      this._number = (this._number * _multi);
      return this;
    }
    
    aNumber.prototype.add = function(_add) {
      this._number = (this._number + _add);
      return this;
    }
    
    aNumber.prototype.subtract = function(_sub) {
      this._number = (this._number - _sub);
      return this;
    }
    aNumber.prototype.ans = function() {
      return this._number;
    }
    
    var a = new aNumber()
    
    alert(a.add(2).subtract(1).ans())

    【讨论】:

      【解决方案6】:

      如果您不想引入库并希望拥有可重用的函数(并且不绑定到特定类,例如计算器)。您可以做的是将输入包装到一个数组中,然后将其传递给一系列映射函数。最后只取第一个元素,你就会得到你的结果。

      function aNumber(){
        var max = 100, min = 0;
        return (Math.floor(Math.random() * (max - min + 1)) + min);
      }
      function divideBy(_number, _divider){
        return (_number / _divider);
      }
      function multiplyBy(_number, _multi){
        return (_number * _multi);
      }
      function add(_number, _add){
        return (_number + _add);
      }
      function subtract(_number, _sub){
        return (_number - _sub);
      }
      
      // #########################################################
      
      var result = [aNumber()]
        .map(item => divideBy(item, 2))
        .map(item => add(item, 5))
        .map(item => multiplyBy(item, 3))
        .map(item => subtract(item, 10))
        [0];
      
      console.log(result);
      

      这可能不是最有效的方式,但通常速度“足够好”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-26
        • 1970-01-01
        • 1970-01-01
        • 2021-01-17
        • 2019-12-30
        • 2018-03-21
        • 1970-01-01
        • 2015-02-21
        相关资源
        最近更新 更多