When talking about the this keyword in JavaScript, you may find the concept quite confusing. The meaning of this changes in different contexts, making it one of the most common challenges JavaScript developers encounter. Understanding the behavior of this in different contexts is key to writing efficient, maintainable code. In this article, we’ll take a closer look at the multiple identities of this in JavaScript. From global scopes to function calls to object methods and constructors, we’ll break down the behavior of this in various contexts to help you better understand and apply this key concept.

  •  Why do we need this?

 To give functions in an object the ability to access the object’s own properties

  •  Let’s look at the following code
let obj = {
    myname:'xiaoxiao',
    age:18,

    bar: function(){ 
        console.log(myname);
    }
 }
 obj.bar()


When executing this code, we will find that it doesn’t print out Tao, but reports an error, why is that? At this point, we change console.log(myname); to console.log(this。myname); , we access myname through this, and it finally prints out successfully.


  • The beauty of this: it can significantly improve code quality and reduce the passing of contextual parameters
function identify(){
    return this.name.toUpperCase()
}

function speak(){
    var greeting = 'Hello i am' + identify.call(this)
    console.log(greeting);
}

var me = {
    name:'xiaoxiao',
}

speak.call(me)


In this code we are in the speak() function and we have created a variable greeting whose value is the splice of the result of 'Hello i am' and identify.call(this) . The call to means that we are binding in the function to in the function. identify.call(this) This call means that we are binding this in the identify() function to this in the speak() function. This is called an explicit binding, and the call() method allows us to manually specify where this should point within the function.


  1. We then call the speak() function on the me object, which binds this from the speak() function to the me object. As a result, this in identify.call(this) will point to the me object, and so the identify() function returns the uppercase form of the name property of the me object.

  2. Finally, console.log(greeting) will print out 'Hello i am XIAOXIAO' where 'XIAOXIAO' is the uppercase form of the name property of the me object.


We can control the pointing of this within the identify() function from within the speak() function. This flexibility allows us to reuse functions in different contexts and dynamically change the pointing of this inside functions.

 Binding rules for this


– [ ] 1. Default binding: When a function is called independently, without any modifiers, the lexical scope under which the function is in effect is wherever this in the function points — (as long as it’s bound by default, this must point to the window)*.

 function foo(){
 console.log(this);
 }
 foo();

 This code prints out the window:

var obj = {
         a: 1,
         foo: function(){
         console.log(this);//obj
     }
 }
 obj.foo()

 And this code prints out the object in the obj:


  • When a function is referenced by the following object (when the function is owned by an object) the function’s this points to the object that references it
const obj = {
  name: 'John',
  greet: function() {
    console.log('Hello, ' + this.name);
  }
};

obj.greet(); // Output: Hello, John


In this example, the greet function is called as a method of the obj object. Inside the greet function, the this keyword points to the object that called it, the obj object, so this.name will output John .


  • Implicitly lost: when a function is chained by multiple objects, the function’s this points to the nearest one
const obj1 = {
  name: 'John',
  greet: function() {
    console.log('Hello, ' + this.name);
  }
};

const obj2 = {
  name: 'Alice'
};
obj1.greet.call(obj2); // Output: Hello, Alice


In this example, the greet function was originally intended as a method on the obj1 object, but the greet function was extracted from the obj1 object via the call method and called on the obj2 object. In this case, the this keyword inside the greet function points to the obj2 object instead of the obj1 object, so the output is Hello, Alice instead of Hello, John .


Implicit loss occurs here because the greet function was expected to be called in the obj1 context, but the context changed to obj2 at the time of the call. In this case, special attention needs to be paid to the context in which the function is called to avoid the implicit loss problem.

 Show bind: call apply bind


  • The call: call method calls a function whose first argument is the object to be set as the function’s execution context. The subsequent arguments are the list of parameters passed to the function
function greet(name) {
    console.log(`Hello, ${name}! My name is ${this.name}.`);
}

const person = {
    name: 'Alice'
};

greet.call(person, 'Bob');


This will print out: Hello, Bob! My name is Alice. . In this example, the call method sets the execution context of the greet function to the person object and passes a parameter 'Bob' to the greet function.


apply: The apply method is similar to the call method, except that its second argument is an array whose elements are passed as arguments to the function.

function greet(name, age) {
    console.log(`Hello, ${name}! I am ${age} years old. My name is ${this.name}.`);
}

const person = {
    name: 'Alice'
};

greet.apply(person, ['Bob', 30]);


This will print out: Hello, Bob! I am 30 years old. My name is Alice. . apply The method sets the execution context of the greet function to the person object and passes two parameters 'Bob' and 30 to the greet function.


bind: The bind method creates a new function and binds the specified object to the execution context of that function. Unlike call and apply , bind does not execute the function immediately, but returns a new function that you can call later.

function greet(name) {
    console.log(`Hello, ${name}! My name is ${this.name}.`);
}

const person = {
    name: 'Alice'
};

const greetPerson = greet.bind(person);
greetPerson('Bob');


This will print out: Hello, Bob! My name is Alice. . bind The method creates a new function greetPerson and binds the person object to the execution context of that function. When the greetPerson function is called later, the person object becomes the this value of the greet function.


In summary, all three methods allow you to explicitly set the value of this inside a function when you call it, and to pass arguments to the function. call While apply is very similar to in terms of setting the function context and passing parameters, bind creates a new function and binds the specified object as the execution context for that function.

  •  new binding: this points to the created instance object
function Person(name, age) {
    this.name = name;
    this.age = age;
}

const person1 = new Person('Alice', 30);
console.log(person1.name); // Alice
console.log(person1.age);  // 30


new Binding is a way of creating a new object that binds the constructor’s this to the newly created instance object. When you call a function using the new keyword, JavaScript performs the following steps:


  1. Create an empty normal JavaScript object (i.e., the empty object {} ).
  2.  Link the prototype of this empty object to the prototype object of the constructor.

  3. Execute the constructor and bind this empty object to this inside the constructor.

  4. If the constructor does not explicitly return an object, this newly created object is returned.


In general, the value of this is dynamic in JavaScript and depends on how the function is called. Understanding the behavior of this is important for proper use of JavaScript functions and object-oriented programming.

By hbb

Leave a Reply

Your email address will not be published. Required fields are marked *