代码之家  ›  专栏  ›  技术社区  ›  Harold

链接到本机Javascript函数

  •  3
  • Harold  · 技术社区  · 8 年前

    如何使用自己的函数链接到Javascript的map()?就像-

    stuff.map(i => i.key).avg()
    

    其中avg()是我自己的函数,用于计算map返回的数组的平均值?


    return this;
    

    这让我可以连锁。

    如果我有

    let stuff = [
      {id: 1, name: 'tuan', country: 'VN', age: 23},
      {id: 2, name: 'nhung', country: 'US', age: 25},
      ...
    
    //my own filter to pass as a param to native filter()
    var filt = x => j => j.country === x;
    
    //my own reducer for an array that computes an average
    let avg = (arr) => (arr.reduce((acc, i) => acc + i) / arr.length);
    

    stuff.filter(filt('VN')).map(i => i.age)
    

    将返回以下内容

    [23, 34, 45]
    

    但是

    stuff.filter(filt('VN')).map(i => i.age).avg()
    

    filter().map().avg() is not a function 
    

    我们如何编写链接到本机函数上的函数?

    5 回复  |  直到 8 年前
        1
  •  4
  •   user6445533 user6445533    8 年前

    方法链接与函数组合不兼容。但是,您可以创建一个容器类型,允许您在方法链接的上下文中组合纯函数,而不是修改内置原型或依赖于子类型:

    function Box(x) {
      return new.target ? (this.x = x, this) : new Box(x)
    }
    
    Box.prototype.fold = function fold(f) {return f(this.x)};
    Box.prototype.map = function map(f) {return new Box(f(this.x))};
    Box.prototype.toString = function toString() {return `Box(${this.x})`};
    
    const id = x => x;
    
    const stuff = [
      {id: 1, name: 'foo', country: 'VN', age: 23},
      {id: 2, name: 'bar', country: 'US', age: 25},
      {id: 2, name: 'bat', country: 'VN', age: 34},
      {id: 2, name: 'baz', country: 'VN', age: 45}
    ];
    
    const filt = x => j => j.country === x;
    
    const avg = (arr) => (arr.reduce((acc, i) => acc + i) / arr.length);
    
    console.log(
      Box(stuff.filter(filt('VN')).map(i => i.age))
      .map(xs => avg(xs))
      .fold(id) // yields 34
    );

    Box map 您可以将函数应用于函子内的值,并获得一个新的函子,其中包含转换后的值。 fold 行为相同,只是返回裸值。

        2
  •  1
  •   Jaromanda X    8 年前

    在Array.prototype上创建一个avg方法

    Array.prototype.avg = function() {
        return this.reduce((a,b) => Number(a) + Number(b)) / this.length;
    }
    var array = [
        { id: 1, key:2 },
        { id: 2, key:3 },
        { id: 3, key:7 },
        { id: 4, key:6 },
        { id: 5, key:4 }
    ]
    var avg = array.map(i => i.key).avg();
    console.log(avg);
        3
  •  1
  •   Alexander Elgin    8 年前

    avg(stuff.filter(filt('VN')).map(i => i.age)) 因为你定义了 avg 期望的函数 arr 作为其论点。您没有扩展 Array 原型带有 平均值 方法

        4
  •  0
  •   Mark    8 年前

    这是因为 map join() 方法:

    var a = [1, 2, 3, 4, 5]
    a.map((i) => i *2 ).join(",")
    

    但是数组没有 avg()

        5
  •  0
  •   Parris    8 年前

    class PizzaCollection extends Array {
       // .. collection specific methods here...
       avg() {
         // you can iterate on `this`
       }
    }
    

    .map、.filter等都将返回PizzaCollection的实例。

    const j = new PizzaCollection(1, 2, 3)
    const k = j.map((num) => num * num)
    k instanceof PizzaCollection // returns true
    k.avg() // returns the avg