It is difficult to say objectively that this is a bad design. But I think there are more elegant ways to solve the problem.
- Does it create extra variables in your area? Yes
- Perhaps this confuses other developers? Yes
You do not need to ask many more questions than before we can agree that there must be a better way.
Two other answers offer alternatives. The first uses Function.prototype.bind , which allows us to set the context for this within another function.
Conceptually, it is elegant, but it can be heavy syntactically and mentally. I find this often leads to huge overflows when you have to write a lot of .bind event handler calls.
The second is the alias self = this , and then use it appropriately depending on what area you are in.
I think this is a bad experience in itself, since code-supporting developers should think about which version they should use, and they need to remember to make the self = this alias at the top of each new context block.
I think the main problem is the fact that Javascript has the this . This is a pretty huge source of general confusion for Javascript programmers, largely because it has been added to make Javascript more comfortable for object-oriented programmers.
Once you start using Javascript in a purely prototype way ( forget new and this ), all these problems go away.
Instead, create a bank class with the usual old objects.
function BankAccount(name, balance) { var account = {}; account.name = name || 'Anonymous Benefactor'; account.balance = balance || 1000; account.withdraw = function(amount) { return (account.balance -= amount); }; account.deposit = function(amount) { return (account.balance += amount); }; return account; }
No matter where we want to refer to the context object ( account ) inside this function, we can do this because Javascript has links and closures. There is no risk that the context object will ever change to window or event .
The inspiration for this style came from a conversation by Doug Crockford .
You can change your code:
angular.module('app',[]). directive('myDir', function(){ var myDir = {}; myDir.state = {a:1, b:2}; return { link: function(scope, elem, attrs){ elem.on('click', function(){ myDir.state.a++; myDir.state.b++; console.log(myDir.state); }); } } });
- You do not need to worry about
.bind . - You do not need to worry about how your context is changing.
However, consider this as a guide. Not like a law. There are a few examples where this definitely acceptable (Angular services spring). Sometimes you have no choice, some libraries and functions will ensure that you change the value of this .
Last thing. If you can use ES6, either initially (Firefox, IO.js, etc.), or through the transpiler (traceur, babel), then you can use the thick arrow syntax.
function foo() { this.bar = 'baz'; element.on('click', event => { console.log(this.bar);
It associates the current value of this with the context of the function block. It works similarly to .bind(this) , but is syntactically lighter.