Skip to content

Instantly share code, notes, and snippets.

@levaleks
Last active August 1, 2023 19:06
Show Gist options
  • Select an option

  • Save levaleks/4a157ae797a180223dcf88d50bc52d48 to your computer and use it in GitHub Desktop.

Select an option

Save levaleks/4a157ae797a180223dcf88d50bc52d48 to your computer and use it in GitHub Desktop.

'this' in JavaScript

The value of this differs depending on how a function is invoked. There're main rules and some exceptions.

Rules

  1. 'new' binding
function Foo() { this.bar = 'bar'; }
const foo = new Foo();
console.log(foo.bar); // => 'bar'
  1. 'explicit' binding
const arbitaryObject = { foo: 'bar' };
function func() { return this.foo; }

func.call(arbitaryObject); // => 'bar'
func.apply(arbitaryObject); // => 'bar'
  1. A special case of explicit binding is 'hard' binding
const arbitaryObject = { foo: 'bar' };
function func() { return this.foo; }

const bindedFunc = func.bind(arbitaryObject);
bindedFunc(); // => 'bar'

You can't override 'hard' binding either via call, apply, or even bind.

const arbitaryObject = { foo: 'bar' };
function func() { return this.foo; }
const anotherObject = { bar: 'baz' };

bindedFunc.call(anotherObject); // => 'bar' <- NOT OVERRIDEN
bindedFunc.apply(anotherObject); // => 'bar' <- NOT OVERRIDEN

If null or undefined passed to call, apply or bind – default (5) binding will be applied

  1. 'implicit' binding (based on property access)
const arbitaryObject = {
  foo: 'bar',
  baz: function () {
    return this.foo;
  },
};

arbitaryObject.baz(); // => 'bar'
arbitaryObject['baz'](); // => 'bar'
  1. 'default' binding

this === undefined in 'strict mode', otherwise it equals 'window' in browser or 'global' in NodeJS

function func() { return this.property; }

func(); // => undefined
  1. Event Handler's binding

In the browser, there is a special this context for event handlers. In an event handler called by addEventListener, this will refer to event.currentTarget.

const button = document.createElement('button');
button.textContent = 'Click me';
document.body.append(button);

button.addEventListener('click', function(event) {
  console.log(this);
})

After clicking output will be <button>Click me</button>

  1. lexical binding (like variables) in arrow functions

Unlike every other form of function, arrow functions do not have their own execution context. Practically, this means that both this and arguments are inherited from their closest non-arrow parent function.

const whoAmI = {
  name: 'Leo Vykhukholev',
  regularFunction: function() {
    console.log(this.name);
  },
  arrowFunction: () => {
    console.log(this.name);
  },
};

whoAmI.regularFunction(); // "Leo Vykhukholev"
whoAmI.arrowFunction(); // undefined
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment