OctaviaLo
OctaviaLo

Reputation: 1396

Creating a simplified underscore _.invoke

I am trying to create underscore's _.invoke function. I can't figure out why I keep getting a TypeError, Cannot read property 'sort' of undefined. I assume this refers to the array being passed into the function, but I can log each array in the collection, so I don't know why undefined in being thrown up.

function each(collection, iteratee, context) {
  let i
  let boundIteratee = iteratee.bind(context)
  if (Array.isArray(collection)) {
    for (i = 0; i < collection.length; i++) {
      boundIteratee(collection[i], i, context)
    }
  } else {
    for (i in collection) {
      if (collection.hasOwnProperty(i)) {
        boundIteratee(collection[i], i, collection);
      }
    }
  }
  return collection
}

function map(collection, iteratee, context) {
  let result = []
  let formula = function(element, index) {
    result.push(iteratee(element, index, context))
  }
  each(collection, formula, context)
  return result
}

function invoke(collection, methodName) {
  let args = Array.prototype.slice.call(arguments, 2)
  let formula = function(array, index) {
    //console.log(array) --> returns arrays in collection...
    return methodName.apply(array, args)
  }
  return map(collection, formula)
}

function sortIt(array) {
  return array.sort()
}

console.log(invoke([
  [3, 1, 2],
  [7, 6, 9]
], sortIt))

Upvotes: 0

Views: 462

Answers (1)

nainy
nainy

Reputation: 540

Depending on what you're trying to achieve, you can either replace your sortIt function with:

function sortIt() { return this.sort(); } // since you apply the arrays as context to the function

or replace

return methodName.apply(array, args);

with

return methodName(array);

Neither are ideal, though.

Also, please look up the apply() method.

Upvotes: 1

Related Questions