Javascript - access to 'this' members from sub-objects

In an object, other than purely aesthetic reasons, I wonder if there is a way to allow access to 'this' members from within sub-objects.

Take this example (which I reflected in http://jsfiddle.net/Wzq7W/5/ ):

function BlahObj() { this.users = {}; } BlahObj.prototype = { userGet: function(id) { if (this.users[id] !== undefined) { return this.users[id]; } }, userAdd: function(id, name) { if (this.users[id] === undefined) { this.users[id] = name; } }, user: { get: function(id) { if (this.users[id] !== undefined) { return this.users[id]; } } } } var test = new BlahObj(); test.userAdd(1, 'User A'); test.userAdd(2, 'User B'); test.userAdd(3, 'User C'); test.userGet(2); test.user.get(1); 

The UserGet () method will correctly return "User B", but due to the scope, user.get () cannot access the base member.

In the context, this object will have many other members and methods that are consistent with it, so the camel camera seems so dirty; the ability to separate them into groups (user.get (), queue.foo (), room.data ()) seems more appropriate in theory. Is it practical? Is there a way to do what I ask in the way I do it, or am I just better off with camelCase?

Thanks for your thoughts!

+4
source share
3 answers

Another friend of mine suggested a loop in the constructor that would bind (), similar to what both @RobG and @Twisol suggested, but without the need for a separate entry for each line.

There are probably other ways to make this cycle so that it is not specific to two levels, but at the moment it can be quite good. Are there any consequences that I should be aware of, in particular performance or other considerations that I cannot take into account?

 function BlahObj() { this.users = {}; for (sub in this) { for (key in this[sub]) { if (typeof this[sub][key] == 'function') { this[sub][key] = this[sub][key].bind(this); } } } } BlahObj.prototype = { userGet: function(id) { if (this.users[id] !== undefined) { return this.users[id]; } }, userAdd: function(id, name) { if (this.users[id] === undefined) { this.users[id] = name; } }, user: { get: function(id) { if (this.users[id] !== undefined) { return this.users[id]; } } } } var test = new BlahObj(); test.userAdd(1, 'User A'); test.userAdd(2, 'User B'); test.userAdd(3, 'User C'); test.userGet(2); test.user.get(1); 
0
source

The UserGet () method will correctly return "User B", but due to the scope, user.get () cannot access the base member.

The keyword value of this has nothing to do with scope. In a function, this is a local variable whose value is set by a call, not how the function is declared or initialized.

You can use ES5 bind to change this (and add a function. Prototype.bind for those environments that don't have one), or you can use closure or a similar strategy instead of this .

Edit

Consider the camelCase option, I think it is much cleaner than creating a sublevel, i.e.

 getUser: function() {...}, addUser: function() {...}, ... 

but not:

 user: { get: function(){}, add: function(){}, ... } 

One character less for input (e.g. addUser vs user.add )

+3
source

Demo

Change this:

 user: { get: function(id) { if (this.users[id] !== undefined) { return this.users[id]; } } } 

To:

 user: function() { var that = this; return { get: function(id) { if (that.users[id] !== undefined) { return that.users[id]; } } }; } 

You should call it like test.user().get(1) instead of test.user.get(1) though

+3
source

Source: https://habr.com/ru/post/1396121/


All Articles