【问题标题】:Is there any way to make a function's return accessible via a property?有什么方法可以通过属性访问函数的返回值?
【发布时间】:2017-10-21 15:34:00
【问题描述】:

我是一名 JS 开发人员,正在尝试函数式编程思想,我想知道是否有任何方法可以按照 promise 链的编写方式将链用于同步函数。

例如:

function square (num) {
  return num * num;
}
let foo = 2 
let a = square(foo) //=> 4
let b = square(square(foo)) //=> 16

很公平,但是我想做的(通常是为了使代码解析更容易)是通过将这些方法作为链的第一个参数传入来将这些方法链接在一起。所以这样的事情会起作用:

let c = square(foo)
          .square()
          .square() //=> 256

有什么方法可以用 vanilla javascript 做到这一点,还是我必须修改 Function.prototype 才能做到这一点?

【问题讨论】:

标签: javascript functional-programming language-features function-prototypes


【解决方案1】:

您不必修改 Function.prototype,而是修改 Number.prototype。您正在尝试创建一个作用于数字而不是函数的新方法。这可以满足您的要求:

Number.prototype.square = function() {
  return this * this;
}

let x = 4;

let y = x.square().square(); // -> 256

【讨论】:

    【解决方案2】:

    修改Function.prototypeNumber.prototype确实是个坏主意,因为你会污染默认的JavaScript对象,比如说:如果其他框架也作恶并添加自己的square怎么办?

    推荐的方法是自己制作一个对象。

    function num(v) {
        this.v = v;
        this.val = function() { return this.v; };
    
        this.square = function() { this.v = this.v * this.v; return this; };
        //and you can add more methods here
        this.sqrt = function() { this.v = Math.sqrt(this.v); return this; };
        return this;
    }
    
    var n = new num(2)
    console.log(n.square().square().sqrt().val());

    【讨论】:

      【解决方案3】:

      您可以将squarenum设置为square调用的属性`

      function square (num) {
      
        if (!this.square) {
          this.square = square;
          this.num = num || 0;
        };
        
        if (num === undefined) {
          this.num *= this.num
        }
        else if (!isNaN(num)) {  
         this.num *= num;
        };
        return this;
        
      }
      
      let foo = 2;
      let c = new square(foo).square().square();
      console.log(c.num);

      【讨论】:

        【解决方案4】:

        您可能对 Identity 函子感兴趣 – 它允许您提升任何函数以对 Identity 的值进行操作 – 例如,下面的 squaremult。无需接触原生原型即可获得可链接的界面 ^_^

        const Identity = x => ({
          runIdentity: x,
          map: f => Identity(f(x))
        })
        
        const square = x => x * x
        
        const mult = x => y => x * y
        
        let result = Identity(2)
          .map(square)
          .map(square)
          .map(square)
          .map(mult(1000))
          .runIdentity
          
        console.log(result)
        // 256000

        【讨论】:

        • 映射整个世界...你知道我的喜好,我仍然 +1 :D
        • 这可能正是我正在寻找的。虽然我不喜欢使用 .map 作为链式函数的名称,但可能会与 Array.prototype.map 混淆。
        • @BrianBoyko 不要太担心 ^_^ 你应该认为它类似于 'Array.prototype.map' 因为它的工作方式相同 – .map获取一个普通函数,将其提升到您的函子中,并允许您操作一个内部值。数组函子;就像身份一样!
        • 老实说,这让我大开眼界。是时候学习一些榆树了
        猜你喜欢
        • 1970-01-01
        • 2018-04-30
        • 1970-01-01
        • 1970-01-01
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多