Five different scenarios of this
Default
By default, pure function calls are regarded as Global calls, where this points to the Global object, which in the browser environment is also called the window object.
window.x = 'Jackie' function func() { console.log(this.x) } func() // Jackie
In strict mode, this is forbidden to point to the global object, which is undefined.
Method calls as objects
This points to the object that calls this method.
var x = 'Property of Window' var obj = {} obj.x = 'Property of obj' obj.f = function () { console.log(this.x) } obj.f() // Property of obj // Notable circumstances var f = obj.f f() // Property of Window
Explicit binding of call, apply and bind
call, apply, and bind can all change the direction of this of a function.
call and apply
call and apply point this of their calling objects to their first parameter.
function f () { console.log(this.x) } var x = 'Property of Window' var obj = { x: "Property of obj" } f.apply(obj) // "Property of obj"
When the first parameter is undefined or not, this will automatically point to the Global object in the non-strict mode, the window object in the browser, and undefined in the strict mode:
function f () { console.log(this) } f.apply() // window f.apply(undefined) // window function ff () { 'use strict' console.log(this) } ff.apply() // undefined ff.apply(undefined) // undefined
call and apply are not essentially different. The only difference is that:
The call() method accepts a list of several parameters, while the apply() method accepts an array of multiple parameters.
bind
There is no essential difference between bind and the previous two, except that bind binds the first parameter to this of the calling function and returns the function (not executed).
function f () { console.log(this.x) } var x = 'Property of Window' var obj = { x: "Property of obj" } var ff = f.bind(obj) ff() // "Property of obj"
Constructor
When a function is used as a constructor to create a new object with the new keyword, this inside the function and this on the prototype chain will point to the new object.
function Jackie(para) { this.para = para console.log(this) } Jackie.prototype.log = function(){ console.log(this) } Jackie('hehe') // Window var p = new Jackie('haha') // Jackie {para: "haha"} p.log() // Jackie {para: "haha"}
Other noteworthy bindings
Put it in super-time code
The code for timeout calls in JavaScript is executed in global scope, so the value of this in the function points to the window object, as well as in strict mode. Because the code for timeout calls has an implicit binding: setTimeout(f, time) == setTimeout(f.bind(window), time).
"use stric" var x = 'Property of Window' var obj = {} obj.x = 'Property of obj' obj.ff = function () { setTimeout( function () { console.log(this.x) }, 100) } obj.ff() // Property of Window // That's how it works out. obj.fff = function () { var that = this setTimeout( function () { console.log(that.x) }, 100) } obj.fff() // Property of obj
this in the event listener function
this in the event listener function points to the listener object.
var one = document.getElementById('one') one.onclick = function () { console.log(this) }; one.click() // <div id="one"></div>
Arrow function
The direction of this in the arrow function is bound when the function is defined and cannot be changed later.
var obj = { x: 1 } var f1 = () => { console.log(this) } f1.apply(obj) // Window var f2 = function () { var f3 = () => { console.log(this) } return f3 } var f4 = f2.apply(obj) f4() // Object {x: 1}
A more magical example is that the code that calls a timeout binds the direction of this when it is defined.
function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42
Priority of binding
var obj = {x: 0, name: 'obj'} var robj = {x: -1, name: 'robj'} var factory = function (x) { this.x = x console.log(this) } var factoryBind = factory.bind(obj) robj.factory = factoryBind robj.factory(2) // Object {x: 2, name: "obj"}, the priority of binding as a method is lower than the explicit binding of bind factoryBind.call(robj, 3) // Object {x: 3, name: "obj"}, call has lower priority than bind console.log(robj) // Object {x:-1, name:'robj', factory: function}, no modification to robj console.log(obj) // Object {x: 3, name: "obj"}, modified obj, because this pointer pointed unchanged var p = new factoryBind(4) // factory {x: 4} console.log(p) // factory {x: 4} console.log(obj) // Object {x: 3, name: "obj"}, the priority of constructor binding is higher than that of explicit binding of bind
As you can see, priority ranges from high to low:
new, construct binding
bind, explicit binding
call/apply, showing bindings
Binding as a method
Default binding