Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using 'this' keyword in JavaScript object

Tags:

javascript

I like to think I understand JavaScript, but I found something unexpected today and I was hoping someone could explain to me why it happens.

Take this code

var animalData = {
                  cow:"cow",
                  sheep:"sheep",
                  getCow:function()
                  {
                    return this.cow;
                  },
                  animalList:[
                          {
                            animalId:this.cow,
                            label:"This is a cow"
                          },
                          {
                            animalId:this.sheep,
                            label:"This is a sheep"
                          }
                       ]
          };

console.log(animalData.getCow());
console.log(JSON.stringify(animalData.animalList,null," "))

The output is not what I was expecting. Calling animalData.getCow() results in "cow" just as you would expect. But it's what gets return by the second console.log that confuses me.

[
 {
  "label": "This is a cow"
 },
 {
  "label": "This is a sheep"
 }
]

In other words, the object removes the animalId property entirely from the objects defined. I was expecting this

[
 {
  "animalId":"cow",
  "label": "This is a cow"
 },
 {
   "animalId":"sheep",
  "label": "This is a sheep"
 }
]

And I could understand maybe this

[
 {
   "animalId":undefined,
  "label": "This is a cow"
 },
 {
   "animalId":undefined,
  "label": "This is a sheep"
 }
]

But why does the animalId property get removed entirely?

Can anyone explain what's going on under the surface to cause this behaviour? I'm guessing that the this keyword does not work because the properties are undefined when it is invoked, but why does it remove the property entirely?

NB: I'm not looking for a workaround, that's easy enough to do - just interested in why it happens.

JSFiddle here

like image 849
Toby Avatar asked May 27 '16 14:05

Toby


People also ask

Can you use this in an object JavaScript?

“this” is not bound In JavaScript, keyword this behaves unlike most other programming languages. It can be used in any function, even if it's not a method of an object. The value of this is evaluated during the run-time, depending on the context.

Do I need to use this in JavaScript?

JavaScript's this keyword is one of the hardest aspects of the language to grasp. But it is critically important for writing more advanced JavaScript code. In JavaScript, the this keyword allows us to: Reuse functions in different execution contexts.

What does '$' mean in JavaScript?

$ is simply a valid JavaScript identifier. JavaScript allows upper and lower letters, numbers, and $ and _ . The $ was intended to be used for machine-generated variables (such as $0001 ). Prototype, jQuery, and most javascript libraries use the $ as the primary base object (or function).

How do I use this keyword?

The this keyword refers to the current object in a method or constructor. The most common use of the this keyword is to eliminate the confusion between class attributes and parameters with the same name (because a class attribute is shadowed by a method or constructor parameter).


2 Answers

At the point the object is initialised, this refers to the outer context, which won't have cow and sheep properties. As you thought, that will result in the animalIds being undefined.

JSON.stringify does certain things with undefined properties, namely:

If undefined, a function, or a symbol is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array).

Which is why you don't see them.

like image 142
James Thorpe Avatar answered Nov 15 '22 20:11

James Thorpe


First of all, you are correct your last example, this is what you are trying to stringify:

[
 {
   "animalId":undefined,
  "label": "This is a cow"
 },
 {
   "animalId":undefined,
  "label": "This is a sheep"
 }
]

And, because those values are undefined JSON.stringify simply omits them. Why the values above are undefined is because the this keyword in this.cow refers to the current scope, which is actually the window Object as it is not inside any other function.

Why it makes sense to omit keys with undefined values? Because whether they exist or not, if you try to access object.key you will get the correct value: undefined

like image 27
XCS Avatar answered Nov 15 '22 19:11

XCS