Adding custom properties to a function

后端 未结 10 790
独厮守ぢ
独厮守ぢ 2020-11-27 10:34

Searching for appropriate answer proved difficult because of the existence of many other problems related to my keywords, so I\'ll ask this here.

As we know, functio

10条回答
  •  暖寄归人
    2020-11-27 11:20

    I agree that this is a difficult question that could have multiple answers, so I prefer to make an different example:

    Let's suppose to have an JavaScript Array, populated by a generator:

    var arr = [...new Array(10).keys()];
    

    that is

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    Now we want to map this to a new array - same length, applying some function, so we could use the native map function property:

    arr = arr.map((value,index) => ++value)
    

    We have just done a value=value+1 and return, so now the array will look like

    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    Ok, now supposed to have a JavaScript Object like

    var obj=new Object()
    

    that was defined like the previous array (for some crazy reason):

    arr.forEach((value,index) => obj[value]=value)
    

    i.e.

    {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
    

    At this point we cannot apply the same map method since it's not defined for an Object so we have to define it as a new prototype of an Object:

    Object.defineProperty(Object.prototype, 'mapObject', {
          value: function(f, ctx) {
              ctx = ctx || this;
              var self = this, result = {};
              Object.keys(self).forEach(function(k) {
                  result[k] = f.call(ctx, self[k], k, self);
              });
              return result;
          }
        });
    

    At this point we could do as for the array before:

    obj=obj.mapObject((value,key) => ++value )
    

    so that we have:

    {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
    

    You can see that we have updated the values only:

    [...Object.keys(obj)]
    ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    

    and we can turn back then into the output array:

    [...Object.keys(obj).map(k=>obj[k])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    Here it is at work:

    // Array.map
    var arr = [...new Array(10).keys()];
    console.log("array", arr)
    arr = arr.map((value, index) => ++value)
    console.log("mapped array", arr)
    // new property
    Object.defineProperty(Object.prototype, 'mapObject', {
      value: function(f, ctx) {
        ctx = ctx || this;
        var self = this,
          result = {};
        Object.keys(self).forEach(function(k) {
          result[k] = f.call(ctx, self[k], k, self);
        });
        return result;
      }
    });
    
    // Object.mapObject
    var obj = new Object()
    arr = [...new Array(10).keys()];
    arr.forEach((value, index) => obj[value] = value)
    console.log("object", obj)
    obj = obj.mapObject((value, key) => ++value)
    console.log("mapped object", obj)
    console.log("object keys", [...Object.keys(obj)])
    console.log("object values", [...Object.keys(obj).map(k => obj[k])])

提交回复
热议问题