this keyword

65 阅读2分钟

key points:

this refers to the current context in which the code is executing. The value of this is determined dynamically based on how and where the function is called:

  1. In the global scope, this refers to the global object.
  2. In regular functions, this depends on how the function is invoked (object method, global function call, etc.).
  3. In arrow functions, this is inherited from the parent function (or the surrounding scope) and does not change based on how the function is called.

Arrow Function

define

  1. Arrow functions inherit this from the enclosing lexical scope, which means they take this from the nearest regular function that encloses them, not from block constructs like if, for, or while blocks.
  2. In other word, this refers to the context of the parent function (or the surrounding scope) where the arrow function is defined.

the nearest regular function

const person = {
  name: 'Alice',
  greet: function() {
    const arrowFunc = () => {
      console.log(this.name); // `this` refers to `person`
    };
    arrowFunc();
  }
};

person.greet(); // Output: "Alice"

Steps:

  • The arrow function inside greet inherits this from its lexical scope.
  • The nearest regular function is greet.
  • When greet is called as person.greet(), the this in greet refers to the person object because it's called as a method on person.
  • Therefore, the arrow function inside greet inherits this from greet, which refers to person.
const person = {
  name: 'Bob',
  greet: function() {
    if (true) {
      const arrowFunc = () => {
        console.log(this.name); // `this` still refers to `person`
      };
      arrowFunc();
    }
  }
};

person.greet(); // Output: "Bob"

Standalone Function Called

this refers to window object

var length 4; 
function callback(){ 
	console.log(this.length);//What is logged? 
} 

const object = {
	length:5, 
	method(fn){ 
		fn(); 
	};
} 
object.method(callback);//4

// actually it is a independent call

Object Method Called

this refers to the object calls method

const objA = { 
  type: "A",
  foo() { 
    console.log(this.type) 
  }
}

const objB = { 
  type: "B",
  foo: objA.foo,
  bar: () => objA.foo(),
  baz() { objA.foo() }
}

objB.foo();
objB.bar();
objB.baz(); 

Passing a function as an argument or callback fuction

When dealing with regular functions passed as arguments or used as callbacks, the behavior of this depends on how those functions are invoked.

Regular Function as Callback

  1. example 1
const obj = {
  name: 'Alice',
  greet: function() {
    setInterval(function() {
      console.log(this.name); // `this` is `undefined` or `window`, not `obj`
    }, 1000);
  }
};

obj.greet(); // Output: `undefined` (or nothing in strict mode)

The setInterval function receive a callback function. The callback function excute by Function call, so this refers to the global object.

  1. example 2
const user = { 
	name:"Piyush Agarwal!", 
	logMessage(){ 
		console.log(this);//What is logged? 
	}, 
} 
setTimeout(user.logMessage,1000); //window

Steps:

  1. By writing user.logMessage, you're referring to the method, but you're not actually calling it. You're simply passing a reference to the function.
  2. When called normally (like user.logMessage()), this would refer to the user object.
  3. When you pass user.logMessage as a callback to setTimeout, it loses its original context (user).
  4. This means that when setTimeout invokes logMessage, it's not called as a method of user, but as a regular function call.

Arrow Function as Callback

  1. example 1
const obj = {
  name: 'Bob',
  greet: function() {
    setInterval(() => {
      console.log(this.name); // `this` refers to `obj`
    }, 1000);
  }
};

obj.greet(); // Output: "Bob" every second

The callback function is arrow function. The arrow fucntions do have this, it inherit from parent function(greet). The greet function was method called, so this refers to the obj object.

  1. example 2
const user = { 
	name:"Piyush Agarwal!", 
	logMessage(){ 
		console.log(this);//What is logged? 
	}, 
} 
setTimeout(()=>user.logMessage(),1000); //window

In this case, logMessage was called by user. This refers to the user object.