Javier Arroyo
Mega Guru

This article is about extracting Array Higher Order methods into functions through a process called demethodize

Method vs Function
A method belongs to an object and is called through a dot.notation.

SomeObject.someMethod();

A function stands alone without being called through an Object.

someFunction();

 

Extracting a method form an Object: demethodize.

function demethodize (mthd) {
    return Function.prototype.call.bind(mthd);
}

The function above returns another function that when supplied with arguments, uses the first argument as the this binding. This happens because calling Function.prototype.call on Function.prototype.bind has the effect of shifting arguments by one.

Think this:

func.apply(thisArg, rest of arguments);

Usage:

var filter = demethodize(Array.prototype.filter);
var reduce = demethodize(Array.prototype.reduce);
var forEach = demethodize(Array.prototype.forEach);

Some functions to test if demethodize works.

//to test filter
function hasAge (item) {
    return item.age;

}

//to test reduce
function addAge (reducer, item) {
    return reducer += item.age;

}

//to test forEach
function print (fn) {
  return function (value) {
     return fn(JSON.stringify(value));
  }
}

Array to use with functions above

var objs = [{
        age: 10
    },
    {
        age: 11
    },
    {},
    {
        age: 12
    }

];

Kicking off the tests

var filtered = filter(objs, hasAge); //filter result to those objects that have age

forEach(filtered, print(gs.debug)); //looking at the filtered result

/*
{"age":10} (sys.scripts extended logging)
{"age":11} (sys.scripts extended logging)
{"age":12} (sys.scripts extended logging)
*/


var totalAge = reduce(filtered, addAge, 0);

gs.debug(totalAge); //33

The constructs above work because demethodize uses the first argument supplied to each function as the this context.

 

Using filter as a side-to-side comparison with conventional SNow practices:

for loopArray.filterdemethodize
var filtered = [];
for( var x=0; x < filtered.length; x++) {
    if ( item.age ) {
        filtered.push(item);
    }
}
var filtered = objs.filter(function (item) {
    if (item.age) {
        return true;
    }
});
var filtered = filter(objs, hasAge);


Hopefully this presents helpful constructs towards cleaner code. Specifically to demethodize, the possibility is to be lazier and only have to code the logic that takes place inside the loop without need to be idiomatic, whether through Array.filter or for loops.

 


Happy snowing...

Version history
Last update:
‎11-02-2020 06:51 PM
Updated by: