In this article, I would like to explain some tricky concepts in JavaScript that can get really confusing, depending on where you are in your development journey. Namely, I’ll discuss object references, scopes, context and instantiation in JavaScript. It should help you understand some behaviors that can otherwise seem odd with JavaScript.
First, an example to illustrate the point:
[] === []
// false
Woah, what just happened an empty array is not equal to an empty array. JavaScript, how confusing can you be!
The concept of object reference can be very tricky, here for example let’s do a check to see if object1
and object2
is the same:
let object1 = { value:10 };
let object2 = object1;
let object3 = { value: 10};
object1 === object2
//true
We get true because both object1
and object2
are both pointing to the same reference data that’s in memory. If we check to see if object1
and object3
is the same:
object1 === object3
// false
Interesting! they both have the same value but why are they not the same. That’s because object3
creates another reference in the memory, which isn’t the same as object1
so JavaScript treats both objects as being different.
To explain further, imagine object1
being created as an address in memory, then object2
pointing to object1
at the same address. While object3
is another address in memory. object1
address can never be the same as object3
address.
Back to the initial example of:
[] === []
// false
In Javascript array’s are really objects behind the scene so JavaScript treats the first []
as a new object and store the reference in memory, then stores the second []
as a different reference in memory, So when checking for equality, it turns out they can’t be the same.
Context are always confused with scopes. A scope is always created when curly brackets are encountered. If we create a function, for example, a new scope is created:
function sampleScope() {
let a = 'a';
console.log(a);
}
If we were to reference the variable a
from outside the sampleScope
function it wouldn’t be recognized because the variable is defined inside the sampleScope
function scope.
A context is different from scope, it tells you the current object we are currently referencing. Context is accessed using the this keyword. For example, if we log the current context we are in from the console in the browser with the following:
console.log(this);
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
It tells us we are currently in the window
objects. The this
is a special keyword of Javascript that point’s to the current object or context:
this.alert('hello');
window.alert('hello);
The two lines above are essentially the same thing because the this
keyword references the window
object because that’s the current context.
If we create a new object like so:
const object4 = {
a: function() {
console.log(this);
}
}
object4.a();
// {a: ƒ}
We see that it logs out the current context which is the object4
context.
Let’s say we want to keep track of the students we had in a classroom by having their names and gender, so we model out a class that looks like this:
class Student {
constructor(name, gender){
console.log(this);
this.name = name;
this.gender = gender;
}
introduceStudent() {
console.log(`${this.name}, ${this.gender}`);
}
}
We have a class that we created accepts a name
and a gender
and also has access to a function that logs the student’s name.
Now let’s say we want to create a class representative without having to copy the same code and adding extra information, we can extend the Student
class while creating a new class for the class representative, like so:
class Rep extends Student{
constructor(name, gender){
super(name, gender);
}
introduceClassRep() {
console.log(`${this.name}, ${this.gender}, and I'm a class rep`);
}
}
The extends
keyword tells JavaScript to add whatever property the class extends from to the current class. Whenever we extend a class, we also need to call it’s constructor method, super
gives us the power to do just that.
Now let’s create instances of both class:
const student1 = new Student('jane', 'female');
const student2 = new Rep('cole', 'male');
After creating these new instances you’ll see that the two console outputs are different. That’s simply because they are instances of different classes.
With JavaScript the behavior of objects can seem quite complicated at first, but understanding the underlining concepts can give you a lot of power and reveal the underlining simplicity.
We’ve looked at how object references, context, scope and instances come to play in JavaScript, and we’ve shown how to use them. Hopefully you now have a better understanding of these more advanced concepts! 🏋
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!