简体   繁体   English

Javascript - 从子对象访问'this'成员

[英]Javascript - Accessing 'this' members from sub-objects

In an object, for nothing more than purely aesthetic reasons, I'm wondering if there's a way to allow access to 'this' members from within sub-objects. 在一个对象中,仅仅出于纯粹的美学原因,我想知道是否有办法允许从子对象内访问“this”成员。

Take this example (which I've mirrored at http://jsfiddle.net/Wzq7W/5/ ): 举个例子(我在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 properly return 'User B', but due to scope, user.get() cannot access the base member. userGet()方法将正确返回“用户B”,但由于范围,user.get()无法访问基本成员。

In context, this object will have many more members and methods that go along with it, so camel-casing seems so dirty; 在上下文中,这个对象将有更多的成员和方法,因此骆驼套管看起来很脏; being able to separate them out by group (user.get(), queue.foo(), room.data()) seems like a better approach in theory. 能够通过组(user.get(),queue.foo(),room.data())将它们分开似乎是理论上更好的方法。 Is it practical? 这是实用的吗? Is there a way to do what I'm asking, in the way I'm looking to do it, or would I just be better off with camelCase? 有没有办法做我想问的方式,就像我想要做的那样,或者我会用camelCase做得更好?

Thanks for your thoughts! 谢谢你的想法!

The userGet() method will properly return 'User B', but due to scope, user.get() cannot access the base member. userGet()方法将正确返回“用户B”,但由于范围,user.get()无法访问基本成员。

The value of a function's this key word has nothing to do with scope. 函数的this关键字的值与范围无关。 In a function, this is a local variable whose value is set by the call, not by how the function is declared or initialised. 在函数中, this是一个局部变量,其值由调用设置,而不是如何声明或初始化函数。

You can use ES5 bind to change that (and add Function.prototype.bind for those environments that don't have it), or you can use a closure or similar strategy instead of this . 您可以使用ES5 绑定来更改它(并为那些没有它的环境添加Function.prototype.bind ),或者您可以使用闭包或类似策略来代替this

Edit 编辑

Consider the camelCase option instead, I think it's much cleaner than creating a sub–level, ie 请考虑使用camelCase选项,我认为它比创建子级别更清晰,即

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

rather than: 而不是:

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

It's one character less to type too (eg addUser vs user.add ) 键入的字符也少一个(例如addUser vs user.add

DEMO 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 have to call it like test.user().get(1) instead of test.user.get(1) though 你必须把它test.user().get(1)而不是test.user.get(1)

Another friend of mine suggested a loop in the constructor that would bind() similar to what both @RobG and @Twisol had suggested, but without having to specifically write out each line. 我的另一个朋友建议在构造函数中使用bind()类似于@RobG和@Twisol所建议的循环,但不必专门写出每一行。

There are probably other ways to do that loop so it's not specific to two levels deep, but this might be good enough for now. 可能有其他方法可以执行该循环,因此它并不特定于两个级别,但现在这可能已经足够好了。 Are there any implications I should be aware of, specifically performance, or other considerations I may not be taking 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM