javascript - How to access the correct `this` inside a callback? -


i have constructor function registers event handler:

function myconstructor(data, transport) {      this.data = data;      transport.on('data', function () {          alert(this.data);      });  }    // mock transport object  var transport = {      on: function(event, callback) {          settimeout(callback, 1000);      }  };    // called  var obj = new myconstructor('foo', transport);

however, i'm not able access data property of created object inside callback. looks this not refer object created other one.

i tried use object method instead of anonymous function:

function myconstructor(data, transport) {     this.data = data;     transport.on('data', this.alert); }  myconstructor.prototype.alert = function() {     alert(this.name); }; 

but exhibits same problems.

how can access correct object?

what should know this

this (aka "the context") special keyword inside each function , value depends on how function called, not how/when/where defined. not affected lexical scope, other variables. here examples:

function foo() {     console.log(this); }  // normal function call foo(); // `this` refer `window`  // object method var obj = {bar: foo}; obj.bar(); // `this` refer `obj`  // constructor function new foo(); // `this` refer object inherits `foo.prototype` 

to learn more this, have @ mdn documentation.


how refer correct this

don't use this

you don't want access this in particular, the object refers to. that's why easy solution create new variable refers object. variable can have name, common ones self , that.

function myconstructor(data, transport) {     this.data = data;     var self = this;     transport.on('data', function() {         alert(self.data);     }); } 

since self normal variable, obeys lexical scope rules , accessible inside callback. has advantage can access this value of callback itself.

explicitly set this of callback - part 1

it might have no control on value of this, because value set automatically, not case.

every function has method .bind [docs], returns new function this bound value. function has same behavior 1 called .bind on, this set you. no matter how or when function called, this refer passed value.

function myconstructor(data, transport) {     this.data = data;     var boundfunction = (function() { // parenthesis not necessary         alert(this.data);             // might improve readability     }).bind(this); // <- here calling `.bind()`      transport.on('data', boundfunction); } 

in case, binding callback's this value of myconstructor's this.

note: when binding context jquery, use jquery.proxy [docs] instead. reason don't need store reference function when unbinding event callback. jquery handles internally.

ecmascript 6: use arrow functions

ecmascript 6 introduces arrow functions, can thought of lambda functions. don't have own this binding. instead, this looked in scope normal variable. means don't have call .bind. that's not special behavior have, please refer mdn documentation more information.

function myconstructor(data, transport) {     this.data = data;     transport.on('data', () => alert(this.data)); } 

set this of callback - part 2

some functions/methods accept callbacks accept value callback's this should refer to. same binding yourself, function/method you. array#map [docs] such method. signature is:

array.map(callback[, thisarg]) 

the first argument callback , second argument value this should refer to. here contrived example:

var arr = [1, 2, 3]; var obj = {multiplier: 42};  var new_arr = arr.map(function(v) {     return v * this.multiplier; }, obj); // <- here passing `obj` second argument 

note: whether or not can pass value this mentioned in documentation of function/method. example, jquery's $.ajax method [docs] describes option called context:

this object made context of ajax-related callbacks.


common problem: using object methods callbacks / event handlers

another common manifestation of problem when object method used callback / event handler. functions first class citizens in javascript , term "method" colloquial term function value of object property. function doesn't have specific link "containing" object.

consider following example:

function foo() {     this.data = 42,     document.body.onclick = this.method; }  foo.prototype.method = function() {     console.log(this.data); }; 

the function this.method assigned click event handler, if body clicked, value logged undefined, because inside event handler, this refers body, not instance of foo.
mentioned @ beginning, this refers depends on how function called, not how defined.
if code following, might more obvious function doesn't have implicit reference object:

function method() {     console.log(this.data); }   function foo() {     this.data = 42,     document.body.onclick = this.method; }  foo.prototype.method = method; 

the solution same mentioned above: if available, use .bind explicitly bind this specific value

document.body.onclick = this.method.bind(this); 

or explicitly call function "method" of object, using anonymous function has callback / event handler , assign object (this) variable:

var self = this; document.body.onclick = function() {     self.method(); }; 

or use arrow function:

document.body.onclick = () => this.method(); 

Comments

Popular posts from this blog

networking - Vagrant-provisioned VirtualBox VM is not reachable from Ubuntu host -

c# - ASP.NET Core - There is already an object named 'AspNetRoles' in the database -

ruby on rails - ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true -