1

I've been reading recently about Functional Programming and Immutable Objects in Javascript. What is the functional programming way of using map method?

Say I want to double values in an array. I can do:

var arr1 = [{a: 1}, {a: 2}, {a: 3}];
arr1.map(function(el){
    el.a = el.a*2;
    return el;
});

// arr1 => [{a: 2}, {a: 4}, {a: 6}]

But this seems to break the rules of functional porgramming and immutability the callback will modify directly elements of the array. Is the following the 'correct' way to do this?

var arr1 = [{a: 1}, {a: 2}, {a: 3}];
var arr2 = angular.copy(arr1);

var arr2 = angular.copy(arr1).map(function(el){
  el.a = el.a*2;
  return el;
});

arr1 = arr2;

// arr1 => [{a: 2}, {a: 4}, {a: 6}]

Or am I simply overthinking this? Fiddle is here.

6
  • But this seems to break the rules of functional porgramming and immutability. How? since map will not modify the existing array, it will return a new one. Commented Oct 14, 2016 at 10:56
  • 1
    @gurvinder372 map itself won't modify, but -> el.a = el.a * 2 will. Commented Oct 14, 2016 at 10:58
  • you should do like var arr2 = arr1.map(el => el*2); Commented Oct 14, 2016 at 11:02
  • If you don't want arr1 to be mutated, then simply return el.a*2; and taking output in arr2 will do the job. Commented Oct 14, 2016 at 11:02
  • @redu Do you mean arr2 = arr1.map(el => {a:el.a*2}) Commented Oct 14, 2016 at 11:04

3 Answers 3

3

You will need to use a pure function that does not mutate its arguments. So if you want objects with the doubled values, you have to create new objects:

 var arr1 = [{a: 1}, {a: 2}, {a: 3}];
 console.log(arr1);
 var arr2 = arr1.map(function(el) {
    return {a: el.a*2};
 });
 console.log(arr2);

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

Comments

2

You may use a pure function, which does not mutate the input object, by simple return something and not assigning something to an element of data.

var arr1 = [{a: 1}, {a: 2}, {a: 3}],
    arr2 = arr1.map(function (el) {
        return  el.a * 2;
    });

console.log(arr2);
console.log(arr1);

Return an array with new objects

var arr1 = [{a: 1}, {a: 2}, {a: 3}],
    arr2 = arr1.map(function (el) {
        return  { a: el.a * 2 };
    });

console.log(arr2);
console.log(arr1);

4 Comments

I suppose it should map back to the item objects with doubled a properties.
I think the OP made things slightly confusing here, as he said the results were // arr1 => [2, 4, 6] , when in fact there [{a:2},{a:4},{a:6}], easy change of course just wrap in a new object literal.
it is a bit unclear, but for changing values inside of the array's objects, i would take forEach and not map and assign the new value in situ.
@Keith Correct, should be [{a: 2}, {a: 4}, {a: 6}]
1

Destructuring assignment would make this pretty nice. Either way tho, you have to make a new object otherwise objects in arr1 will be modified.

let arr1 = [{a: 1}, {a: 2}, {a: 3}];
let arr2 = arr1.map(({a}) => ({a: a * 2}))

console.log(arr1); // [{a: 1}, {a: 2}, {a: 3}]
console.log(arr2); // [{a: 2}, {a: 4}, {a: 6}]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.