Created: 2023-02-23 19:19
Status: #concept
Subject: Programming
Tags: JavaScript Scope Closure Constructors

Lexical Scope

The context is what this evaluates to.

  • any variables/objects/functions defined in its parent scope, are available in the scope chain.

var name = 'Todd';
var scope1 = function () {
  // name is available here
  var scope2 = function () {
    // name is available here too
    var scope3 = function () {
      // name is also available here!
    };
  };
};
// name = undefined
var scope1 = function () {
  // name = undefined
  var scope2 = function () {
    // name = undefined
    var scope3 = function () {
      var name = 'Todd'; // locally scoped
    };
  };
};

How this Evaluates - Depending on Scope

var myFunction = function () {
  console.log(this); // this = global, [object Window]
};
myFunction();

// when methods or functions are
var myObject = {};
myObject.myMethod = function () {
  console.log(this); // this = Object { myObject }
};

var nav = document.querySelector('.nav'); // <nav class="nav">
var toggleNav = function () {
  console.log(this); // this = <nav> element
};
nav.addEventListener('click', toggleNav, false);

How to Solve JavaScript Object Method Functions this Function Binding

In this example, this context is changed when we pass the object.method to another Function.

class Button {
  constructor(value) {
    this.value = value;
  }

  click() {
    alert(this.value);
  }
}

let button = new Button("hello");
setTimeout(button.click, 1000); // undefined
In order to solve this, we wrap button.click into a Callback Function wrapper: setTimeout(() => button.click(), 1000)

Another way to solve this is by using JavaScript Classes and create a Class Field that is assigned to a Callback Function Expression and this will always refer to the Object Instantiation every time.

class Button {
  constructor(value) {
    this.value = value;
  }
  click = () => {
    alert(this.value);
  }
}

let button = new Button("hello");
setTimeout(button.click, 1000); // hello

References