2

I'm working on building a JavaScript function that assigns enumerable properties of the source object(s) to the destination object. However, subsequent sources overwrite property assignments of previous sources.

Example if called as such:

extend({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });

should return --> { 'user': 'fred', 'age': 40 }

Bonus: Use Reduce

This is an exercise/challenge for a programming boot camp and I've researched endlessly to find a solution to this. My issue here is that the test objects are not contained within an array so I cannot use reduce to manipulate them. I've attempted multiple ways of altering the test objects such Array.prototype.slice.call(arguments).

Still learning, so if there are any oversights or considerations please let me know. I've been at it for a while so I'm pretty confident there could be some simple mental mistakes

I'm currently unable to pass all the tests provided with the code I have.

Sample code:

function extend(destination) {
    var args = Array.prototype.slice.call(arguments);

    var result = args.reduce(function (newObj, currentObj) {
        for (var key in currentObj) {
            if (currentObj.hasOwnProperty(key)) {
                newObj[key] = currentObj[key];
            }
        }
        return newObj;
    }, {});

    return result;
}
DarrickTM
  • 21
  • 3

2 Answers2

1
function extend(...objs){
 return objs.reduce((newobj,obj)=>Object.assign(newobj,obj),{});
}

The ... Operator returns an array of arguments. So you can reduce it, and use Object assign to copy the props... http://jsbin.com/xamoremati/edit?console , funnily that doesnt override...

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 2
    Side note: Spread syntax isn't available in all browsers. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator – TheJim01 Feb 15 '17 at 18:01
  • @TheJim01 but as this is a coding challenge, it will be availlable in most browsers when he enters productional environments... – Jonas Wilms Feb 15 '17 at 18:05
  • Agreed. I was simply leaving a note for anyone who finds this question later. If that's beyond the scope of comments, I'll remove it. – TheJim01 Feb 15 '17 at 18:08
  • @TheJim01 no, i wanted to add it too, you were slightly faster. – Jonas Wilms Feb 15 '17 at 18:09
  • Really appreciate the information, it could be because I'm new to arrow syntax or what, but I was unable to pass all the tests with this function. – DarrickTM Feb 15 '17 at 18:27
  • @DarrickTM funnily it doesnt override ( wich ive expected)so barney will stay barney. The main point is the ... and the reduce, you may replace the Object assign with a good old for loop, like you already did in your code... – Jonas Wilms Feb 15 '17 at 18:29
  • Thank you, @Jonasw. I really appreciate you taking the time to help me out and tips! – DarrickTM Feb 15 '17 at 18:32
  • @DarrickTM i just noticed that i positioned the arguments (newobj, obj) in the wrong order. Should work now... – Jonas Wilms Feb 15 '17 at 18:35
0

Turn your arguments list into an array, then use reduce how you normally would.

function extend(){
  var inputArray = [];
  for(var i = 0, len = arguments.length; i < len; ++i) inputArray.push(arguments[i]);
  return inputArray.reduce(function(acc, val){
    var keys = Object.keys(val),
        key = null;
    for(var keyIdx = 0, len = keys.length; keyIdx < len; ++keyIdx){
      key = keys[keyIdx];
      acc[key] = val[key];
    }
    return acc;
  });
}

var results = extend({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); // { user: "fred", age: 40 }

Alternate loop approach as discussed in the comments:

function extend(){
  var inputArray = [];
  for(var i = 0, len = arguments.length; i < len; ++i) inputArray.push(arguments[i]);
  return inputArray.reduce(function(acc, val){
    for(var key in val){
      acc[key] = val[key];
    }
    return acc;
  });
}
TheJim01
  • 8,411
  • 1
  • 30
  • 54
  • Thank you! I was able to work the tests with this approach. For your portion of code: var keys = Object.keys(val), key = null; for(var keyIdx in keys){ key = keys[keyIdx]; acc[key] = val[key]; can you explain in layman's terms how you're working through this? I'm more well versed in array notation and less in object notation – DarrickTM Feb 15 '17 at 18:27
  • 2
    @DarrickTM the Object.keys is unnecessary. Simply do for(var keyIdx in val). Object keys returns an array of the objects keys... – Jonas Wilms Feb 15 '17 at 18:32
  • @Jonasw is correct, it's unnecessary in the scenario (using the `for(in)` approach). If you were going to use a `for` loop with a true counter, exploding the keys into an array could be useful (or you could just keep a counter yourself). – TheJim01 Feb 16 '17 at 14:20
  • 1
    [Don't use `for…in` enumerations on arraylikes!](https://stackoverflow.com/q/500504/1048572) – Bergi Feb 16 '17 at 14:33