The value of this differs depending on how a function is invoked. There're main rules and some exceptions.
- 'new' binding
function Foo() { this.bar = 'bar'; }
const foo = new Foo();
console.log(foo.bar); // => 'bar'- 'explicit' binding
const arbitaryObject = { foo: 'bar' };
function func() { return this.foo; }
func.call(arbitaryObject); // => 'bar'
func.apply(arbitaryObject); // => 'bar'- 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 OVERRIDENIf null or undefined passed to call, apply or bind – default (5) binding will be applied
- 'implicit' binding (based on property access)
const arbitaryObject = {
foo: 'bar',
baz: function () {
return this.foo;
},
};
arbitaryObject.baz(); // => 'bar'
arbitaryObject['baz'](); // => 'bar'- 'default' binding
this === undefined in 'strict mode', otherwise it equals 'window' in browser or 'global' in NodeJS
function func() { return this.property; }
func(); // => undefined- 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>
- 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