0

So this is the prompt that I am currently doing:

Define a function mapObject that accepts the same arguments as map except it works for Objects. You must then use mapObject and use it on the input given below. Then define a callback function, format, to be passed into mapObject so that we get the output below. format should receive two arguments, the key and value.

The input is an object, output is object with formatted values. You can hard code "biography" in format; Do not hard code anything else Do not create any other functions

so this is the example of the object (no known variable name).

example:

console.log(mapObject(input, format));
Input:

{
    firstName: "James",
    lastName: "Hu",
    gender: "Male",
    biography: "Oh hey, I'm just a guy"
}
Output:

{
    firstName: "JAMES",
    lastName: "HU",
    gender: "MALE",
    biography: "oh hey, i'm just a guy"
}

my current solution is as follows:

var mapObject = function(object, callback) {
    var newObject = {};

     for (let key in object) {

     newObject[key] = callback(key, object[key]);

  }
  return newObject;
};

var format = function(key, value) {
  if (key === "biography") {
    return value.toLowerCase();
  } 
  else {
    return value.toUpperCase();
  }
};

Everytime I run the code, I return, cannot read property should of undefined. Can someone help me to figure out what I am doing wrong?

1
  • 1
    it looks like you're missing some code in your first function. there is a closing curly brace that makes it look like you're missing an if check. Commented Dec 1, 2017 at 1:38

2 Answers 2

1

You have made good progress. Here are some further pointers in the right direction (but this is not complete...you will need to fill in a few details so that I don't rob you of the learning experience). Note: edited to return new object in the style of native map function.

var mapObject = function(object, callback) {
  var newObject = {}
  // You need to get each key of the object and then
  // call 'callback' on object.key and assign it back to the object
  newObject[key] = callback(key, object[key])

  // when all done, return the reformatted object
  return newObject;
}    

Your format function looks good.

var format = function(key, value) {
      if (key === "biography") {
        return value.toLowerCase();
      } else {
        return value.toUpperCase();
      }
};

Since you are required to have your format function take two arguments (key and value), you need to get each key from the object and call function on that element. For the incomplete code I have provided to work properly you will need to add a loop to process each key. Hint: for(key in object) or Object.keys and .forEach().

If you still run stuck post your latest attempt and we can help some more.

Edit to further explain forEach and for.

As requested, here is a bit more detail on using forEach. You call forEach on an array, so you first need to get the keys of your object. Like this:

Object.keys(object).forEach(function(key) {
  // now do something with key
})

Try to incorporate that approach into your code.

But another way is just to us a for loop since javascript is smart enough to get the keys for you:

for(var key in object) {
      // now do something with key
}
Sign up to request clarification or add additional context in comments.

5 Comments

+1. Minor complaint: the idea of a map function is to return a new collection without mutating the original one. So it would be better not to do overwrite the value of object[key] but rather set the key property on a new object.
@MattBrowne Good point. I edited my answer to make this change.
Ok so I added in a for..in loop to the top, but I'm stuck because now I have a type error of cannot read property of toUpperCase on undefined. I do not have to add a conditional statement to my loop, since I want the value to be assigned to my new array since its already understood, correct?
nevermind I figured out my error: thank you so much! I'll update my question in case this helps anyone else.
@Eric I would like to know how to properly use the forEach property. I'm a newbie to javascript and learning the methods.I know it takes a function callback as its parameter. So would the proper way of using for each would be: object.forEach(callback(currentValue, index, array)? I tried using forEach but I would get a token error.
0

Could be like:

var doc, bod, I, objMap, old = onload; // for use on other loads
onload = function(){
if(old)old(); // change old var name if using technique on other pages
doc = document; bod = doc.body;
I = function(id){
  return doc.getElementById(id);
}
objMap = function(obj, func){
  var h, o = {};
  for(var i in obj){
    h = func(i, obj[i]);
    for(var n in h){
      o[n] = h[n];
    }
  }
  return o;
}
var yourObj = {
 firstName:'James',
 lastName:'Hu',
 gender:'Male',
 biography:'Oh hey, I'm just a guy'
}
var newObj = objMap(yourObj, function(k, v){
  var nk = k, nv = v, o = {}
  if(k !== 'biography'){
     nv = v.toUpperCase();
  }
  if(k === 'firstName'){
    nk = 'lookTheKeyChanged';
  }
  if(v === 'Male'){
    nv = 'Look the value changed';
  }
  o[nk] = nv;
  return o;
});
var out = I('out'), txt = '';
for(var i in newObj){
  txt += i+' : '+newObj[i]+'<br />';
}
out.innerHTML = txt;
}
/* external.css */
html,body{
  padding:0; margin:0;
}
body{
  background:#000; overflow-y:scroll;
}
.main{
  width:936px; background:#ccc; padding:20px; margin:0 auto;
}
#out{
  background:#fff; padding:10px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
  <head>
    <meta http-equiv='content-type' content='text/html;charset=utf-8' />
    <meta name='viewport' content='width=device-width' />
    <title>objMap</title>
    <link type='text/css' rel='stylesheet' href='external.css' />
    <script type='text/javascript' src='external.js'></script>
  </head>
<body>
  <div class='main'>
    <div id='out'></div>
  </div>
</body>
</html>

newObj first argument is your object, second argument is a function that takes the key and the value. The return object sets the new key and value, at each step.

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.