JavaScript函数编程 - 链接函数和使用匿名函数

时间:2017-04-10 21:08:25

标签: javascript functional-programming method-chaining dot-operator

当我在尝试将函数应用于值时遇到问题时,我在CodeWars上做了一个问题并练习了一些函数式编程。

所以我创建了一个 pass()函数,它接受一个函数作为参数,这样我就可以使用匿名函数来操作该值,然后返回它。因此,在这种情况下,它从reduce中获取值并将其传递给函数,以便它可以操作该值然后返回它。

WORKS 我真的不想在Object原型中添加方法!

如何在保持功能链接的同时以另一种方式做到这一点?

简单示例

Object.prototype.pass = function(fn) {
  return fn(this);
};

var value = 1;

var new_value = value.pass(function(num){
   return num + 1;
});

console.log(value, new_value); // Outputs: 1 2

CodeWars上下文问题

Object.prototype.pass = function(fn) {
  return fn(this)
};

function digPow(n, p) {
  return n
    .toString()
    .split('')
    .reduce(function(total, num, i) {
      return total + Math.pow(parseInt(num), (p + i))
    }, 0)
    .pass(function(total) {
      return (total % n == 0) ? Math.floor(total / n) : -1;
    });
}

//digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
console.log("Test Case 1 returns (", digPow(89, 1), ") should return 1")

//digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
console.log("Test Case 2 returns (", digPow(92, 1), ") should return -1")

//digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
console.log("Test Case 3 returns (", digPow(695, 2), ") should return 2")

//digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
console.log("Test Case 4 returns (", digPow(46288, 3), ") should return 51")

Code Wars说明

  

有些数字有趣。例如:

     

89 - > 8¹+9²= 89 * 1

     

695 - > 6²+9³+5⁴= 1390 = 695 * 2

     

46288 - > 4³+6⁴+2⁵+8⁶+8⁷= 2360688 = 46288 * 51给出a   正整数n写成abcd ...(a,b,c,d ......是数字)和   一个正整数p我们想找到一个正整数k,如果它   存在,例如取连续的n的数字之和   p的幂等于k * n。换句话说:

     

是否存在整数k,例如:(a ^ p + b ^(p + 1)+ c ^(p + 2)+ d ^   (p + 3)+ ...)= n * k如果是这种情况,我们将返回k,如果不返回   -1

     

注意:n,p将始终以严格正整数给出。

2 个答案:

答案 0 :(得分:1)

解决方案只是不使用方法链接 - 要应用于结果的功能不是它的方法。有各种各样的方法:

  • 一个简单的变量:

    function digPow(n, p) {
      const total = n
        .toString()
        .split('')
        .reduce(function(total, num, i) {
          return total + Math.pow(parseInt(num), (p + i))
        }, 0);
      return (total % n == 0) ? Math.floor(total / n) : -1;
    }
    
  • IIFE调用(这种方法适用于静态函数):

    function digPow(n, p) {
      return (function(total) {
        return (total % n == 0) ? Math.floor(total / n) : -1;
      }(n
        .toString()
        .split('')
        .reduce(function(total, num, i) {
          return total + Math.pow(parseInt(num), (p + i))
        }, 0));
    }
    
  • 实验bind operator(对于静态“方法”也更好):

    function digPow(n, p) {
      return n
        .toString()
        .split('')
        .reduce(function(total, num, i) {
          return total + Math.pow(parseInt(num), (p + i))
        }, 0)
        :: function() {
          return (this % n == 0) ? Math.floor(this / n) : -1;
        }();
    }
    

您还可以使用pass“方法”中的任何方法。

答案 1 :(得分:1)

您也可以使用Identity仿函数。这为您提供一个可链接的界面,但不接触本机原型



const Identity = x => ({
  runIdentity: x,
  map: f => Identity(f(x))
})

const digPow = (n, p) =>
  Identity(n)
    .map(n => n.toString())
    .map(str => str.split(''))
    .map(nums => nums.reduce((total, num, i) =>
      total + Math.pow(parseInt(num, 10), p + i), 0))
    .map(total => total % n === 0 ? Math.floor(total / n) : -1)
    .runIdentity

console.log(digPow(89, 1))  // 1
console.log(digPow(695, 2)) // 2




如果定义了一些可重用的函数,它会稍微清理一下代码



const Identity = x => ({
  runIdentity: x,
  map: f => Identity(f(x))
})

const split = x => str => str.split(x)
const reduce = f => y => xs => xs.reduce(f, y)

const digPow = (n, p) =>
  Identity(n)
    .map(String)
    .map(split(''))
    .map(reduce((acc, x, i) => acc + Math.pow(Number(x), p + i)) (0))
    .map(x => x % n === 0 ? Math.floor(x / n) : -1)
    .runIdentity

console.log(digPow(89, 1))  // 1
console.log(digPow(695, 2)) // 2