Can I See Your References?


#1

This is probably easy but worked for 4 days and now can't remember. This is the question.

Take a look at the james object. Complete the sayJob method so that it will print to the console "Hi, I work as a [job]", where [job] is the value of the job property.

Then in line 14, change the job for james to "super programmer".

var james = {
    job: "programmer",
    married: false,
    sayJob: function() {
        // complete this method
        this.job = job;
        console.log("Hi, I work as a " + job);
    }
};

// james' first job
james.sayJob();

// change james' job to "super programmer" here
var james = { job: "super programmer"};

// james' second job
james.sayJob();

#2

Alright, the error is on line 14:

var james = { job: "super programmer"};

You've already initialized the object variable of "james", on line 1, so you'll not need to do so again. And this is probably where you're getting your error message.

So instead of reinventing the wheel let's pass the sayJob function an argument. "Wait!" you say, "the sayJob: function doesn't have any parameters to push a argument through!" And you'd be right so we'll have to fix that too!!

First let's fix line 14 by essentially copying the lines 11, and 17. (These will have to be changed to but we'll get to that.)

james.sayJob("super programmer"); /*This tells the "sayJob" function in the "james" 
object to change the job that "james" has to "super programmer"  */

Next!

sayJob: function(){
    this.job = job; //The console is now saying "I have no idea what I'm suppose to do.
    console.log("Hi, I work as a " + job);
}

So let's change that!

sayJob: function(job){
    this.job = job; //Now I can use the "job" argument I'm getting from the function!
    console.log("Hi, I work as a " + job);
}

Final changes!:

On lines 11, and 17. Change the open parenthesis to have an argument of james.job.

james.sayjob(james.job); //This tells the console to use "james" current "job:"

I really hope this helps!


#3

Ah i was thrown off by the Hint which says to not use a parameter in the method.

You should use this.job inside your method. It should not be a parameter,

Edit must be a touchy excercise I get the correct output with your updates but no pass.

Hi, I work as a programmer
Hi, I work as a super programmer


#4

alright, it turns out I did this way back in 2012, and since then they've changed passing conditions. I was able to fix the error and move on to the next exercise but I still think the other way was much better!

Here's the passing code.

var james = {
    job: "programmer",
    married: false,
    sayJob: function() {
        // complete this method
        console.log("Hi, I work as a " + this.job);
    }
};

// james' first job
james.sayJob();

// change james' job to "super programmer" here
james.job = "super programmer";

// james' second job
james.sayJob();

#5

And for reference it passed this code? not sure why.I was just peicing it back peice by peice when it passed.

var james = {
    job: "programmer",
    married: false,
    sayJob: function() {
        // complete this method
    this.job = job;
      console.log("Hi, I work as a", job);    
    }
};

// james' first job
james.sayJob();

// change james' job to "super programmer" here


// james' second job
james.sayJob();

#6

We would never write this,

james.sayJob(james.job);

Both job and sayJob are properties of the james object. The method can see the job property in its present context, this which is the james object internal reference.

var james = {
    job: "programmer",
    married: false,
    sayJob: function () {
        console.log("Hi, I work as a", this.job); 
    }
};

Now we can run the method on the james object:

james.sayJob(); // Hi, I work as a programmer

Changing the property simply means giving it a new definition by assigning a new value:

james.job = "super programmer";
james.sayJob(); // Hi, I work as a super programmer

Looking at the code in the above post,

this.job = job;

will never fly. job is a variable in window context, and as yet undefined, so the line effectively sets the job property to undefined (or throws a ReferenceError if job is not declared yet). This line,

console.log("Hi, I work as a", job);

will output, Hi, I work as a undefined (or throw a ReferenceError)

Study up on context as it relates to objects, and scope as it relates to functions. These two are easy to confuse. Learning their real meaning is important.


#7

I'm confused as to why you would never use james.sayJob(james.job)?

Let's say in a more specific use of the program you would need to pass a variable as an argument through a function, but you just wanted to pass the function an argument of the object that it was already in. E.G passing job: "programmer" to the function of sayJob. How in that case would you go about doing such a thing if my method was an incorrect solution (albeit not a correct solution to the current lesson)?


#8

Because we don't need to pass an argument. sayJob can already see the job property since they are properties of the same object. That is where this comes in. Inside the function it refers to the object context, james.


#9

In this lesson you would be correct, and I was wrong for trying to pass that argument through the function, but I'm talking about utilizing that in a function from outside of the lesson. Would it be POSSIBLE to pass that kind of argument through a function, or are you saying that it's just impractical?


#10

It is impractical to pass an identifierName to a method of the same object.

job        // identifier
james.job  // identifierName

Any property that is part of the same object is in the same context. this resides outside of a function, not in, so it is technically global in scope. When a method refers to this.job it is not in local scope of the function, but above it. this is the context within which the method is executing.

Since we have context, we don't need to pass any variables that share in it. Our methods may have parameters of their own, but they will not have object context, and may be some other values or objects that exist outside of the object (or in formal parameters).

Consider the following:

var lunchMenu = {
    mon: [],
    tue: [],
    wed: [],
    thu: [],
    fri: []
};
james.lunchToday = function (day) {
    console.log(lunchMenu[day]);
}
james.lunchToday('mon');

The lunchMenu object is not in james object context, and none of the members of the object can see the variable day,since it is in local scope of a function.


#11

Taking the above to different level,

var lunchMenu = {
    mon: [],
    tue: [],
    wed: [],
    thu: [],
    fri: []
};

// copy the global to a property
james.lunchMenu = lunchMenu.slice(); 

// now james can have his own menu

james.lunchToday = function (day) {
    console.log(this.lunchMenu[day]);
}
james.lunchToday('mon');

Starting to make sense? (I can tend to go in circles, sometimes.)


#12

No it makes sense. I think I'm just on another train of thought than you. At the same time I can see that there would be ways around the issue I'm describing as well so furthering the point would be moot. Thank you anyway! I know it took a lot of time to type that out so thank you for your contribution!


#13

Sorry if I'm not reading your question. I sense some confusion around context and this, as well as the close-knit nature of object members. Pardon my assumption.

Going back over my last example, just discovered I used an array method on an object.

"TypeError: lunchMenu.slice is not a function"

This is a working example:

var lunchMenu = {
    mon: ['Chicken Noodle Soup','Turkey Sandwich'],
    tue: [],
    wed: [],
    thu: [],
    fri: []
};
lunchMenu.clone = function(){
    var pClone = {};
    for (var key in this){
        pClone[key] = this[key];
    }
    return pClone;
};
var james = {};

// copy the global to a property
james.lunchMenu = lunchMenu.clone(); 

// now james can have his own menu

james.lunchToday = function (day) {
    console.log(this.lunchMenu[day]);
};
james.lunchToday('mon');

#14

With first class functions and context it empowers javascript to do some amazing things easily.

That includes confusing me with **this.

Thanks for taking the time for the extra explanations.


#15

The object through which a method is invoked becomes the value of the this keyword within the body of the method. - Flanagan.

So this is essentially a helper within each object to enable the sharing of its attributes for use in methods.


#16

All functions have an execution context which is referable with this. Variables within the present context are accessible by referring to their identifierName, this.variable. It even applies in the global window context.

As we saw above,

var fizbaz = "bar";

function foo() {
    return "foo" + this.fizbaz;
}
console.log(foo()); // foobar

In this case, this is window, the execution context of the function.

var myObj = {
    fizbaz: "bar"
}
myObj.foo = foo;

console.log(myObj.foo()); // foobar

Now the execution context is myObj. By assigning a function reference to an object property, we make that object the execution context for the function.


#17

Edited to enforce shadowing:

var fizbaz = "bar";

function foo() {
    var fizbaz;
    return "foo" + this.fizbaz;
}
console.log(foo()); // foobar

Now the global is no longer visible in the function since there is a locally defined variable of the same name. It doesn't have any effect on this.fizbaz, though. That is still the correct reference (for the example).


#18

Thank you mtf! Seeing it done wrong and then corrected is invaluable. I really enjoyed/learned a lot from this post!


#19

2 posts were split to a new topic: sayJob function not properly logging


#22

A post was split to a new topic: Not getting any output only job is undefined