Table of content:
- Keyword this overview
- Band of call-site cases
- Default binding
- Implicit binding
- Explicit binding
- new binding
- Priority
- Arrow functions and this
this
overview
Keyword this
is a dynamic context of the function, that defined by call-site (added to call-stack
during the call).
Example:
function foo () {
console.log(this.a)
}
This function will output different values in order to the context of its calling.
Band of call-site cases
So, how do these types look? What is the context in those cases?
A brief overview of what is this
:
- default binding -
global object
/undefined
in strict mode - implicit binding - object contained called method
- explicit binding - object passed as context using
call
/apply
/bind
(works like the default fornull
/undefined
as context) new
binding - created object
Default binding
By default this is referred to the global object, or to undefined in strict mode:
var a = 'bar'
function foo1 () {
console.log(this.a)
}
function foo2 () {
'use strict'
console.log(this.a)
}
foo1() // 'bar'
foo2() // Cannot read property 'a' of undefined
Implicit binding
When a function is a method, this refers to the object contained that method:
var a = 'global bar'
function foo () {
console.log(this.a)
}
var obj = {
a: 'bar',
foo,
}
obj.foo() // bar
Explicit binding
You can explicit set the context using call
/apply
methods:
function foo () {
console.log(this.a)
}
var context = {
a: 'bar'
}
foo.call(context) // bar
Note: call
/apply
get a function arguments after context value, and the difference is that call
gets a list of arguments while apply
gets singe argument - an array of arguments.
Also, you can create a new function that will hardbound to the context using the bind
method.
new
binding
And, the last but not least binding to creating object during constructor call
:
function Foo (a) {
this.a = a
console.log(this.a)
}
var foo = new Foo('bar') // 'bar'
console.log(foo) // { a: 'bar' }
Priority
The power of binding types in order as we examined them:
- default binding
- implicit binding
- explicit binding
- new binding
Note: you can’t use new binding with call
/apply
methods, but can with bind
, that will ignore bound context for constructor calls:
function foo (a) {
this.a = a
}
var context = {}
var boundFoo = foo.bind(context)
boundFoo('boundFoo call')
console.log(context) // { a: 'boundFoo call' }
var boundFooInstance = new boundFoo('boundFoo call')
console.log(context) // { a: 'boundFoo call' }
console.log(boundFooInstance) // foo { a: 'boundFoo call' }
this
Arrow functions and Arrow functions offered by ES6
, have a special behavior with this
keyword, actually, they just get a value of the enclosing (function/global) scope.
We can use that improvement for passing a function as callbacks to save out context inside other functions, like setTimeout
:
var a = 'global bar'
function foo () {
setTimeout(function() {
console.log(this.a) // global bar
}, 100)
setTimeout(() => {
console.log(this.a) // bar
}, 200)
}
foo.call({ a: 'bar' })