JavaScript Objects | “this”​

Aniket Jha
6 min readApr 5, 2020

Objects in the real world have some behaviour attached to them. For example, a user on messenger can chat, view profile etc. These behaviour are the function linked to the user object.

“this” happened
const userObject = {
name: 'Aniket',
age: 22,
};
userObject.myName = function (){ // (1) way
alert('myName method');
};
function myAge(){
alert('myAge method');
}
userObject.myAge = myAge;
userObject.myName(); // alert: myName method

Here we have created a Function expression and assigned it to `userObject.myName` property, this function as a property is called a method.

Method shorthand

Method shorthand exists which are declared directly on object literal itself like so:

userObject = {
myName: function (){
// implemetation
},
myAge() {
// implementation
},
};

`myAge` and `myName` functions are method shorthand that is directly declared on object literal. They are slightly different during inheritance. But that’s a topic for another article.

“this” in method

In Javascript, `this` is `dynamically scoped`. 🤔

Dynamic Scoped

💡A function’s `this` keyword references the `execution context` for that call and determined entirely by how the function was called.

💡`this` aware function thus can have different context each time it is called which makes it flexible and reusable. This is called Dynamic Scoping and `this` behaviour is different from other languages like Java.

Need for “this”

In Javascript, `this` is used to refer a object inside `function/ method` call. Like so:

var userObject = {
name: 'Aniket',
myName(){
console.log('this', this.name); // (1)
console.log('object', userObject.name); // (2)
}
};
userObject.myName(); // (3)
// used to access object ref inside method / function
// this Aniket
// object Aniket
var userObject2 = userObject; // (4) Assigning userObject ref
userObject2.name = 'Jane'; // (5) changes name property at ref
userObject = null; // (6) Removed refernce to user object
userObject2.myName(); // (7) TypeError: Cannot read property of null

In the above illustration, the `userObject` was declared and the method was created on it. The method/ function is `this` awareness and thus when called like `userObject.myName()` the function is called on `userObject` object and refer `this` as `userObject` object.

💡 In the above case for (3), `userObject.myName()` where myName property is called from `userObject` thus context,` this` will refer to `userObject`.

🏷️ (1) this.name gives ‘Aniket’. Here this refers to `userObject. `(2) `userObject.name` directly access name property stored on `userObject.`

🏷️ (1) `this` is used and it dynamically refers to the context from where it was called, here it is `userObject. `(2) `userObject` is directly referring to the object itself so reads directly from there.

🏷️ (1) `this.name` referred the `context(userObject)` dynamically and context were determined at point method was called. (2) userObject.name statically refer to `userObject.` It doesn’t change no matter how it is called.

💡 In the above case for (4) we assigned the `userObject reference to userObject2.` Note Objects are reference type and thus both `userObject and userObject2 refer to the same section in memory. Reference assigning for objects types is not the same as value assigning for primitive types.`

💡 In the above case for (5) we are modifying the value of property name at memory referred by userObject2. As both user object and userObject2 refer the same section of memory the value is changed for both. Confirm this by putting a console.log(userObject.name, userObject2.name) immediately after (5);

💡 In the above case for (6) we put `null` into userObject which means userObject no longer refer to object in memory. Rather refers to a null value.

💡 In above case for (7) we call `userObject2.myName()` which call `myName(`) method with context userObject2.

🏷️ (1) `this` will refer to userObject2 and thus access property name on it.(2) userObject currently holds null and thus `.myName() method/ property doesn’t exist on null`

🏷️ (1) We saw use case how `this behaves dynamically and help us to refer context.`(2) This way was unreliable and thus should not be used.

Ways to call a function and “this” variance

Ther are four ways a function can be called.

Implicit way

The way we have seen in the above illustration is called Implicit way.

const userObject = {
name: 'Aniket',
myName() {
console.log(this.name);
}
};
userObject.myName(); // implict way

myName() function is called from userObject thus the context is userObject and this points to userObject

Bound way

ABC of function is one way to call some function in a different context.

function myName() { // (1)
console.log(this.name);
};
const userObject = {
name: 'Aniket',
};
const userObject2 = {
name: 'Jane',
};
// userObject.myName(); Error
// call myName function with context as userObject
myName.call(userObject2); // (2) Aniket
// call myName function with context as userObject2
myName.call(userObject2); // (3) Jane

In the above illustration, we demonstrate how C (call) in ABC of functions work. (1) function myName is free and is not declared on userObject thus userObject.myName will be undefined and userObject.myName() is error as undefined is not a function. Now we want to call myName() with context as userObject and userObject2 this is done using ABC of function. ABC of functions calls our function with the context of the specified object.

A common 🤷‍♂️ problem we face with this is loosing the this binding in callbacks. Illustrated as:

const userObject = {
name: 'Aniket',
myName(){
console.log(this.name);
},
};
userObject.myName(); // 'Aniket'
setTimeout(userObject.myName, 1000); // undefined or Error -- depends if strict mode or not

Here we pass our function/ method as a callback which and depending on the mode of operation output could be undefined or Error.

Consider following to understand how method call works:

const userObject = {
name: 'Aniket',
myName(){
console.log(this.name);
},
};
userObject.myName(); // 'Aniket'
const myName = userObject.myName; (1)
myName(); // undefined or Error -- depends if strict mode or not

Steps:

  1. The dot operator retrieves the object.method property.
  2. Then () call that function

🤔 But how does this information is passed to method?

To make object.method() calls work, the dot ’.’ returns not a function ref, but a value of the special internal type called “Reference Type.”

The “Reference Type” is a “Specification Type” internally used by language itself and we cannot use it explicitly. The “Reference Type” has a triplet combination give as (base, name, strict) where

  • base denotes the object on which function is called.
  • name is property name/method name.
  • strict is true if use strict is used.

base is utilized as this inside method call.

The property userObject.myName is not a function but Reference type value.

// Refernce type if strict mode is in effect
(userObject, "myName", true)

💡When () are called on Reference type, they receive full information about object userObject and set base = this = userObject.

💡Reference type is an internal type that has the purpose to pass information from . to calling ().

💡Operation like const myName = userObject.myName; ignore Reference type and takes the value of the function and pass it on to myName variable. Thus this binding is lost.

💡 The value of this is only passed correctly if the function is called directly using dot object.method().

To solve the problem faced during callback we use B(bind) of ABC of function. It creates a hardbound function and gives us reference of that function ensuring it will be called with this pointing to a specified object. const myName = userObject.myName.bind(userObject) will return a hardbound function. And setTimeout(myName, 1000); will work correctly.

Constructor call

function Person(name){
this.name = name;
};
// new Person(); putting "new" in front of function call hijack function
var aniket = new Person('Aniket');
aniket.name; // Aniket

Steps:

  • Create a brand new object
  • Link that object to another object
  • Call function with “this” set to the new object
  • If the function doesn’t return anything “this” is implicitly returned.

The function gets hijacked with the new keyword in front while calling. In case 4 steps are always followed. A brand new object is created out of thin air and “this” points to that object inside the function call

Global/ Default

function myName(){
console.log(this.name);
}
myName(); // (1)

myName is this aware function and called but in (1) call it without specifying context and thus js try to rescue you by referring global object as the this value for the function. The default behaviour of referring global object doesn’t work in strict mode instead this is equal to undefined and thus Error as undefined.name is not a property.

--

--