Javascript - доступ к элементам this из подобъектов - PullRequest
4 голосов
/ 13 февраля 2012

В объекте, по не более чем чисто эстетическим причинам, мне интересно, есть ли способ разрешить доступ к элементам 'this' изнутри подобъектов.

Возьмите этот пример (который я 'отражено в 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);

Метод userGet () будет правильно возвращать «Пользователь B», но из-за области действия user.get () не может получить доступ к базовому члену.

В контексте, этот объект будет иметь гораздо больше членов и методов, которые идут вместе с ним, поэтому верблюжий корпус кажется таким грязным: возможность разделить их по группам (user.get (), queue.foo (), room.data()) кажется более подходящим в теории. Насколько это практично? Есть ли способ сделать то, что я прошу, так, как я этого хочу, или мне было бы лучше с camelCase?

Спасибо за ваши мысли!

Ответы [ 3 ]

3 голосов
/ 13 февраля 2012

DEMO

Изменить это:

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

Кому:

user: function() {
    var that = this;

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

Вы должны назвать это как test.user().get(1) вместо test.user.get(1) хотя

3 голосов
/ 13 февраля 2012

Метод userGet () будет правильно возвращать «Пользователь B», но из-за области действия user.get () не может получить доступ к базовому члену.

Значение ключевого слова this функции не имеет ничего общего с областью видимости. В функции this - это локальная переменная, значение которой устанавливается вызовом, а не тем, как функция объявлена ​​или инициализирована.

Вы можете использовать ES5 bind , чтобы изменить это (и добавить Function.prototype.bind для тех сред, в которых его нет), или вы можете использовать замыкание или подобное стратегия вместо this.

Редактировать

Вместо этого рассмотрим вариант camelCase, я думаю, что он намного чище, чем создание подуровня, т.е.

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

вместо:

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

Текст вводится на один символ меньше (например, addUser против user.add)

0 голосов
/ 13 февраля 2012

Другой мой друг предложил цикл в конструкторе, который связывал бы (), аналогично тому, что предлагали @RobG и @Twisol, но без необходимости специально записывать каждую строку.

Возможно, есть другие способы сделать этот цикл, так что он не относится только к двум уровням, но на данный момент этого может быть достаточно. Есть ли какие-либо последствия, о которых мне следует знать, в частности, о производительности или других соображениях, которые я, возможно, не принимаю во внимание?

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);
...