0

In ES5, I know that it's possible to assign methods to an object using a forEach loop in the following way:

var myMethods = [
  {
    name: 'start',
    src: someFn
  },
  {
    name: 'stop',
    src: someOtherFn
  }
];

var myObject = {};

myMethods.forEach(function(method) {
  myObject[method.name] = method.src;
});

In ES2015 (or ES6), is it possible to define these methods in tandem with creating the object? Here is an example of how I might expect this to work:

// example
const myObject = {
  [...myMethods.map((method) => method.name)]: [...myMethods.map(method) => method.src)]
}

The end result would look like this:

const myObject = {
  start: someFn,
  stop: someOtherFn
}

If there is a way to iterate over these methods and assign them to myObject, I would happily restructure the myMethods array so that this is possible.

The end goal is to be able to assign each of these methods in an external module and not have to duplicate the definition.

3 Answers 3

5

Yes, you can use Object.assign and the spread operator in conjunction with computed property names to do

var myObject = Object.assign({}, ...myMethods.map(({name, src}) => ({[name]: src})));

First we map myMethods to an array of little one-property objects, whose key is given by the value of the name property and value by the src property. Then we use the spread operator ... to pass these to Object.assign as parameters. Object.assign then glues them all together for us.

Sign up to request clarification or add additional context in comments.

2 Comments

A+ Nice one-liner and detailed explanation
Never use this code in production. That's great that it can be done in few symbols, but it wastes a lot of computer time to create unnecessary objects: jsperf.com/assign-vs-reduce/4 Reduce is probably better for that case
3

Reduce should do the trick for you. Note that the optional second parameter is used to start with an empty object at the beginning.

var myMethods = [{
  name: 'start',
  src: function() {
    console.log('started')
  }
}, {
  name: 'stop',
  src: function() {
    console.log('stopped')
  }
}];

var myObject = myMethods.reduce((obj, method) => {
  obj[method.name] = method.src;
  return obj;
}, {})


console.log(myObject)
myObject.start()
myObject.stop()

2 Comments

Fair enough, but I'm going to go ahead and assume that using reduce is new to OP, otherwise he'd already have been using it over that forEach solution
You can also use Object.assign. e.g. myMethods.reduce((obj, method) => Object.assign(obj, {[method.name]: method.src}), {}); so you get some ES6 goodness.
0

Try assigning to myObject at same line of myMethods assignnemts

var myObject = {};

someFn = function(){console.log(this)};
someOtherFn = function(){console.log(this)};

var myObject = {};

someFn = function(){};
someOtherFn = function(){}

var myMethods = [
  {
    name: (myObject["start"] = "start"),
    src: (myObject["start"] = someFn)
  },
  {
    name: (myObject["stop"] = "stop"),
    src: (myObject["stop"] = someOtherFn)
  }
];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.