I find myself assigning "this" to a variable so I can easily use it in callbacks and closures.
Is this bad practice? Is there a better way of referring back to the original function?
Here is a typical example.
User.prototype.edit = function(req, res) { var self = this, db = this.app.db; db.User.findById('ABCD', function(err, user)) { // I cannot use this.foo(user) self.foo(user); }); }; User.prototype.foo = function(user) { };
Do you normally use this approach or have you found a cleaner solution?
a callback is executable code that is passed as an argument to other code. Closure - a closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables.
Callbacks and closures are used frequently in JavaScript. Callbacks are functions that are passed into another function as an argument. Closures are functions that are nested in other functions, and it's often used to avoid scope clash with other parts of a JavaScript program.
Callbacks make sure that a function is not going to run before a task is completed but will run right after the task has completed. It helps us develop asynchronous JavaScript code and keeps us safe from problems and errors.
There are three main ways to deal with this
in callbacks:
The two most common names for this new variable are that
and self
. I personally prefer using that
because browsers have a global window property called self and my linter complains if I shadow it.
function edit(req, res) { var that = this, db.User.findById('ABCD', function(err, user){ that.foo(user); }); };
One advantage of this approach is that once the code is converted to using that
you can add as many inner callbacks as you want and they will all seamlessly work due to lexical scoping. Another advantage is that its very simple and will work even on ancient browsers.
Javascript functions have a .bind()
method that lets you create a version of them that has a fixed this
.
function edit(req, res) { db.User.findById('ABCD', (function(err, user){ this.foo(user); }).bind(this)); };
When it comes to handling this
, the bind method is specially useful for one-of callbacks where having to add a wrapper function would be more verbose:
setTimeout(this.someMethod.bind(this), 500); var that = this; setTimeout(function(){ that.doSomething() }, 500);
The main disadvantage of bind
is that if you have nested callbacks then you also need to call bind
on them. Additionally, IE <= 8 and some other old browsers, don't natively implement the bind
method so you might need to use some sort of shimming library if you still have to support them.
The more primitive ways to control function parameters in Javascript, including the this
, are the .call()
and .apply()
methods. They let you call a function with whatever object as their this
and whatever values as its parameters. apply
is specially useful for implementing variadic functions, since it receives the argument list as an array.
For example, here is a version of bind that receives the method to bind as a string. This lets us write down the this
only once instead of twice.
function myBind(obj, funcname){ return function(/**/){ return obj[funcname].apply(obj, arguments); }; } setTimeout(myBind(this, 'someMethod'), 500);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With