This forum is now read-only. Please use our new forums! Go to forums

0 points
Submitted by superchicK922
over 9 years

4/30 Wondering why we need to use the this keyword to specify job?

Hello I got my code to run and display but only after I added the this keyword as placeholder object in front of property job inside object james: console.log("Hi, I work as a " + this.job);

My understanding is that the this keyword is a useful placeholder to allow multiple, different objects to access the same properties or methods— however, I’m wondering why was it necessary to use it in this case inside a single object – why couldn’t I just access the value of jobs for james by simply saying job considering the fact that I’m inside the object brackets and therefore I’d assume the properties would have scope to be referenced by merely their name…

Just curious of whether there’s something I overlooked in my understanding of the this pointer. Any brief explanations would be very much appreciated! Thanks :)

Answer 545d803452f8639e31001006

84 votes

Permalink

This may come up in later lessons. Notice that we have written the method inside the object literal:

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

In the above, sayJob is dedicated to the james object. But what if we have other objects that similarly have a job property? Do we write (or clone) this same method in those objects? Answer: no. We define the function outside the object where any object can reference it. Consider three objects,

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

james.sayJob = sayJob;
mary.sayJob = sayJob;
bob.sayJob = sayJob;

Now all of these are owners of their respective sayJob() instance. There is only one function, not one for each. this is what makes it possible to have multiple owners. They only really own their instances, not the function itself.

james.sayJob(); // Hi, I work as a programmer
mary.sayJob(); // Hi, I work as a typesetter
bob.sayJob(); // Hi, I work as a designer

The upcoming units that cover object constructors and prototypes will further enlighten you in respect to this.

points
Submitted by Roy
over 9 years

28 comments

skinnygiraffe over 9 years

thanks for enlightening this fact i was getting confused too

Claudia Gonzalez over 9 years

Thanks, this clarifies a TON

Darryl Bodkin over 9 years

beautifully explained. thanks!

JoyceJie over 9 years

very clear explanation. thanks a lot.

Nikhil Balyan about 9 years

thanx it made the concept of this pointer crystal clear to me!

jaredhuch about 9 years

Awesome explanation, thanks

Czarnyjarl about 9 years

good work :)

bigearn about 9 years

I’m not sure this answers OP’s question for me. This is a great explanation as to why you should keep a function like this outside the scope of a single object instance. I get that. But my question is still…IF I’m including the function inside this particular instance (james), then why is [this.] needed at all? Why doesn’t just [job] work? If the scope of the function is restricted to this instance, then what else could [job] be referring to?

Again, I’m not saying that putting the function inside the james instance is the way to go. I honestly have no idea if it’s good practice. I assume this lesson instructs me to do it that way simply to make a point. But if I were to do it…why doesn’t a simple [job] work?

ayylee about 9 years

If you just use [job], it will be looking for a global variable (ie, a variable defined outside of the object). You need to use this.someVariable so the computer knows you’re talking about a property of the object, not a global variable.

Have a look at these two examples I just made. The first one is correct because the method references properties of the object, while the second is referencing global variables outside of the object.

Correct: http://jsfiddle.net/jalnt/9jzuwauo/1/

Wrong: http://jsfiddle.net/jalnt/9jzuwauo/2/

Kiy-Hong Tang about 9 years

@tajom Your explanation together with the jsfiddle examples were super useful

ayylee about 9 years

Glad I could help :)

Drogo Hom about 9 years

Thanks man, kept trying ‘this’ out of the object, kept giving me error..

Prafull about 9 years

@Roy Man you’re good at demonstrations…

Islam Sabr about 9 years

what if you would use just +job instead of +this.job?

Roy about 9 years

Then you would be referencing a global variable, not an instance variable. job is not defined, so will throw a reference error. instance.job is defined within each object instance, and instance inside the function is ‘this’.

Justin Chaloupka almost 9 years

@Roy – doesn’t “this” inside the function refer to the function itself and not the parent object? Would creating a “self” variable set to a passed instance of “this” be the actual solution? Ex.: sayJob: function( this ) { var self = this; console.log( “Hi, I work as a “ + self.job ); };

Roy almost 9 years

sayJob: function( this ) function is already in this context so no parameter needed. this is the owner object, an instance perhaps of a Person class, or if not that, a plain object, the name of which is the owner object, and therefore , ‘this’. When things start getting complicated within a function, it is useful to clone ‘this’ as ‘self’, but in a basic scenario it is redundant and serves no purpose while leaking memory.

Roy almost 9 years

this is to context, as function is to scope. A function written in global scope will have ‘window’ context. Consider. var a='global'; function foo(){var a='local'; console.log(a, window.a, this.a);} foo(); Output : local global global. Now add this code and comment the foo() call. obj = { a: 'object' }; obj.foo = foo; obj.foo(); Output: local global object

Michael Smith almost 9 years

@Roy: what do you mean by ‘window’ context? what does window.a mean?

Roy almost 9 years

The Window object is the context in which everything is housed. It is the top of the global scope chain.

Roy almost 9 years

what does window.a mean? When we declared var a='global' we essentially added a property to the Window object. That property is, window.a. This is good to know since what if we run into a function that has its own variable, a and we for some reason need to access the global a? Simple. Inside the function, a is the locally scoped variable, and window.a is the globally scoped one. We can still access it from inside a function that has a variable of the same name.

Roy almost 9 years

Remember, variables are scoped to where they are declared, not where they are defined. That’s why scoping and variable declarations should always be planned ahead of time. What gets hoisted for permanent use, and what gets garbage collected. I barely see this through the fog, so don’t sweat it if these concepts are still a blur.

Sam over 8 years

great explaination yet not working for me!

Roy over 8 years

@Sam, here is where to post a new Question: https://www.codecademy.com/forums/objects-ii/0/exercises/3

Sam over 8 years

@Roy thanks will do.

William Tan over 8 years

Hi, Roy, thanks.

Joseph Berman over 8 years

This is a great explanation. I’m still unclear as to why you have to enter james.sayJob = sayJob; but hopefully I’ll get it moving forward

Roy over 8 years

sayJob is a generic function written with a this variable to identify execution context. When we set a property of the same name on a defined object (such as ‘james’) to reference that function (not invoke it) then the object can invoke it on its own context.

Answer 547e454e631fe94635000894

14 votes

Permalink

I see you understand how this keyword works in Javascript, so here’s the real answer to your question, as to why it’s best practice to use this:

You are absolutely correct that you could easily do:

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

But what if you were to go back and rewrite your code and you changed var james to var john?

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

You’ll get an error that james is undefined, or similar. If you keep this, you have fewer lines of code to maintain.

points
Submitted by Meg
over 9 years

4 comments

bigearn about 9 years

It makes perfect sense to me why this.job is better than james.job, for no other reason than you might later change the name of the object. But why doens’t a simple [job] work? Why do you need to be any more specific than that, if the function is already restricted to this particular object instance, regardless of what it’s called?

Roy about 9 years

[job] is not a variable, objectName[‘job’] and objectName.job are. job is an identifier outside of object scope. In object scope, james.job is an identifierName. ‘identifier => attribute`.

bigearn about 9 years

Got it! You’re right, I was approaching it as if [job] were a var. But it’s not. There is NO scenario in all of JS were you can reference an object property, whether inside or outside an instance, without including the name of the instance itself. I just needed to be smacked out of that train of thought. Thanks!

Roy about 9 years

Try this in the console: job = “Programmer” [Enter] window.job [Enter] this.job [Enter]. Window is the instanced object when in global scope. There is still object reference, except the root doesn’t need object scope on its variables, so identifier === identifierName. In EVERY other case, as you have mentioned, the instance is paramount (else we could end up with something that has been defined globally getting into the fray)

Answer 545d798c7c82ca3eca0011fc

6 votes

Permalink

All objects in JS are instances. The owner is given by the reference, or identifier. When we access properties inside a function, this is the identifier currently in scope of the function. Eg.

james.sayjob = function(){
    console.log("Hi, I work as a " + this.job);
};

james is the owner, the object in function scope. this.job is actually james.job.

points
Submitted by Roy
over 9 years

Answer 545daf99631fe9afa7001449

3 votes

Permalink

I understand how this works, I’ve already completed the track although I’m sure this will be useful to others mulling over how the this pointer works. My question was, given my understanding of this and as you’ve reiterated here, if the this pointer is meant to be used as a placeholder for multiple objects, why would it be necessary inside a singular object literal like object james – no other object is inheriting the sayJob function in that case because it is defined ONLY in the james object. As you say, in this case, “sayJob is dedicated to the james object”. However, my code wouldn’t run without the this pointer in front of job inside the sayJob function when running with just the single object james. I was wondering why it was necessary for me to do that. Still, FANTASTIC explanation. Thank you taking the time to post it.

points
Submitted by superchicK922
over 9 years

1 comments

Meg over 9 years

That’s not due to fault in your code, it’s due to the test runner the site uses to evaluate your code. Simply put, the test is expecting this.job, although james.job works too.

Answer 5524a73386f5528206000245

3 votes

Permalink

@Justin Chaloupka,

Here is the sample code from in my comment:

var a='global'; 
function foo(){
    var a='local'; 
    console.log(a, window.a, this.a);    
} 
//foo(); // local global global
obj = {
    a: 'object'
};
obj.foo = foo;
obj.foo(); // local global object

In the lab: context vs scope

points
Submitted by Roy
almost 9 years

Answer 556a133193767614e500035b

1 vote

Permalink

console.log(“Hi, I work as a “ + james[‘job’]);

I used the literal constructor syntax and it worked fine…. although both object constructor and literal constructor would work fine I suppose, However it is best practice for what I have come to realise so far or better it is safer to use the “This” keyword ….this.job…..

points
Submitted by samuelvarejames
almost 9 years

1 comments

Roy almost 9 years

this can have any object context, james is just one object. The range of application is limited to it.

Answer 546aa128631fe97a2a00206c

0 votes

Permalink

It doesn’t /own/ the function, it only uses it as a sort of “snapshot”, and it just so happens that while the function is inside of the james object, it can only be used by james. If you were to say job it wouldn’t know where to direct the “snapshot”. That is my understanding of it explained with simplicity… Please let me know if I’m wrong. :D

points
Submitted by Phase-Jitter
over 9 years

3 comments

Roy over 9 years

Owning a function is probably not the best terminology, but owning an instance of a method could be easily characterized in the snapshot analogy you’ve given, here. I wouldn’t say you are wrong any more than I would say that I am right. But if it gives us a clearer picture of what we’re dealing with, anything helps, imho.

Roy over 9 years

When we think about it, all functions are owned by some object, going right back to global functions belonging to the ‘window’ object. alert() and window.alert() are the same function.

Nathan about 9 years

Wow… strange thing JavaScript is!

Answer 55654b87e0a300689200037e

0 votes

Permalink

Supplemental

Scope and Context

In JavaScript, the function has a very special role. It is an object, which we can see in the prototype chain, but it has a constructor (other than Object), meaning a function is actually a class. We know what that means. Its prototype is packed full of goodies. One of them,this, the context variable, is in scope with everything in the function body, including the parameters as given in the other nifty property,arguments.

Given these properties, and the nature of scope, we can see how nesting functions creates many levels of scope. Any variable declared with var in any function immediately identifies with the scope of that function.

The tricky thing to see at first is how the scope chain works. When we reference a variable, JavaScript first looks in the scope where the reference is made for that variable. This is why var a in a function trumps var a outside of it. But what if a doesn’t exist in the current scope? JS goes looking up the scope chain to the next level. If it is found there, then that’s what gets used.

We can have a function in a function in a function in a function, and still JS will find an a at some level, or throw an error. ReferenceError: ‘a’ is not defined, or some such message.

That’s what scope is more or less about. Where is the variable declared? Where we use it, or where we define it is not a factor in determining scope. Only where it is declared. Consider this expression:

var a;
(function(){    
    (function(){        
        (function(){            
            (function(){                
                (function(){
                    a = "Finally, I get defined";
                })();                
            })();            
        })();        
    })();    
})();
console.log(a);

This is some mighty powerful stuff, so we are on our best if we soak it all in. There are a dozen ways we can explore and demonstrate scope in this basic construct. I hope the reader does. And definitely read up on this, as if I need to press that point at this stage.

An object, no matter how it is constructed or what is in its prototype can only ever have one context, itself; I am. That’s my context. roy.birthday = "not saying; getting old". birthday is in roy context. It’s sort of like scope, but not the same thing. john.birthday = "John who?". Now we’re in john context. Both object instances can have the same constructor, but they may also have completely different scope. It all depends upon where the instances were declared.

Oh what a tangled web we weave. Yes, it’s a blitheringly confusing subject but one we must tackle and get akin to. Separate the two and you have won. Confuse the two, and the battle is just begun.

points
Submitted by Roy
almost 9 years

4 comments

bubbagumpSHRIM almost 9 years

baby roy, you are the best and this clears up a lot of misconceptions i had. but can you please tell me why the code below works when it doesn’t print anything to the console? this happened in the section before, but I understood why my code was right in that section. In this section it seems like my code doesn’t make any sense in that adding “james.job=james.sayJob” somehow makes it correct according to codecademy.

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

// james’ first job

james.sayJob(“Fry cook”);

// change james’ job to “super programmer” here james.job = james.sayJob

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

Roy almost 9 years

james.sayJob(), no argument. james.job = “super programmer”; james.sayJobj(); again, no argument. The method only reports the current property value for job. “programmer,” then, “super programmer.”

Roy almost 9 years

When we set a variable to receive a return value from a function, then we should be sure the function returns a value. A function that does something procedural often has no return value, such as is the case with jame.sayJob(). There is no defined return value, therefore the assignment to a variable will be undefined.

Roy almost 9 years

When we assign a name reference only to a function that is already defined, that reference may invoke the function to which it refers. james.sayJob = sayJob is a name reference, only. To invoke this we will use james.sayJob().

Answer 55808107d3292ffbd700035b

0 votes

Permalink

I couldn’t have any answer when I post it. I don’t know why.

var jules = { job: “développeur”, fiance: false, disJob: function() { // completez cette methode console.log(“Salut, je travaille comme “ + this.job); } };

// premier job de jules jules.disJob();

// changez le job de jules pour mettre “super développeur” ici jules.job = “super développeur”;

// second job de jules jules.disJob();

points
almost 9 years

2 comments

Roy almost 9 years

This is from the French language track, isn’t it? Will have to dig to find which lesson, but you can help. Which lesson is it, please?

Ellen Sun over 8 years

It’s lesson 4/30 and I’m having the same problem. I get an error saying the string isn’t properly logged.

Answer 55c506249113cb448500004f

0 votes

Permalink

I just passed 4/30 in the Français track with this code:

var jules = {
    job: "développeur",
    fiance: false,
    disJob: function() {
        // completez cette methode
        console.log("Salut, je travaille comme " + this.job);
    }
};

// premier job de jules
jules.disJob();

// changez le job de jules pour mettre "super développeur" ici
jules.job = "super développeur";

// second job de jules
jules.disJob();
points
Submitted by Roy
over 8 years

Answer 55d2289d9113cb71bc00029f

0 votes

Permalink

Another way to look at it is say you have a variable number: 0; inside some class and you have a method printNumber() and it has a variable defined as number: 5; within the method console.log(number) which one will be printed? the variable within the method of course. Why? well because if you wanted to access the variable outside the method you would have done something like console.log(this.number) or console.log(objectName.number) . To sum it up the this keyword becomes very useful along the lines of scoping and it’s even more useful when you’re utilizing class constructors where properties and methods can vary within each instance of the class that’s where this can also refer to a particular instance of the class.

points
Submitted by fun Tertain
over 8 years