2013-10-15 2 views
1

Я строю библиотеку, которая грубо изложена следующим образом. Есть пара переменных, обработчик событий и метод, который приводит к запуску соответствующего события. Наконец, я продлеваю сделку с собственностью. Это идет как это (я добавил некоторые ///... где я вырезается другой код):Можете ли вы получить доступ к объектно-определенному свойству в частном методе в JavaScript?

$.collidR = function (options) { 

    /// ... 

    var hubName = 'CollidRHub'; 
    var hubProxy = connection.createHubProxy(hubName); 

    /// ... 

    hubProxy.on('registrationComplete', function (username, hasChanges) { 
     $(window).triggerHandler(events.onRegistrationComplete, { username: username, hasChanges: hasChanges }); 
     log(username + " has successfully registered for this entity."); 

     // capture current user 
     this._currentUser = username; 

     // hook for catching up when user joins after edits 
     if (hasChanges) { 
      log("There are outstanding changes for this entity..."); 

     } 
    }); 

    /// ... 

    this.registerClient = function() { 
     /// does some stuff that makes registrationComplete fire 
     /// ... 
    }; 

}; 

Object.defineProperty($.collidR.prototype, "currentUser", { 
    get: function() { 
     return this._currentUser ? this._currentUser : ""; 
    } 
}); 

Обратите внимание, что выше this._currentUser = username немного не похоже на работу. Я думаю, что это проблема с инкапсулированием, к чему и идет этот вопрос.

В отдельной, но связанной библиотеке я создаю экземпляр collidR, и мне нужно ответить на событие. У меня есть обработчик для этого устанавливается следующим образом:

$(window).on(collidR.events.onEditorsUpdated, function (e, data) { 

    /// ... 

    users.forEach(function (user) { 
     var currentUser = collidR.currentUser; 

     // here, currentUser is always default of "" 
     if (user != currentUser) { 
      /// ... 
     } 
    }); 

}); 

Вот что я вижу:

  1. Мои registrationComplete пожаров событие и обработчик успешно
  2. вызывается из отладчика, this._currentUser не определено до того, как значение установлено
  3. линия this._currentUser = username выполняется и значение устанавливается
  4. Когда onEditorsUpdated эв лор пожары, collidR.currentUser всегда значение по умолчанию (пустая строка) в моем обработчике

Что чувствует испорченным где я определить свойство - после того, как остальная часть объекта. Это как если бы я изменял прототип объекта после определения метода, который пытается ссылаться на свойство ... это не может быть прав.

Я также пробовал this.currentUser (во внутреннем методе), но имел тот же результат.

Я предположил, что если прототип был расширен до того, как был вызван внутренний метод, когда я сделал var currentUser = collidR.currentUser;, что я получил бы значение из свойства, но это всегда пустая строка.

Есть ли способ зарегистрировать недвижимость раньше?

Есть ли правильный способ установить значение, чтобы я мог получить к нему доступ позже через открытое свойство?

+0

Что такое '' '' '' '' ', когда вы делаете' this._currentUser'? –

+0

переменная 'collidR' во втором фрагменте, это экземпляр' $ .collidR'. я имею в виду, это определило его с 'collidR = new $ .collidR' или ярлыком $ .collidR? – Bharath

+0

@Bharath - это экземпляр, определенный как вы предлагаете с помощью 'var collidR = new $ collidR;'. – MisterJames

ответ

5

Потому что this в this._currentUser = username; не так, как вы думаете. Значение this в JavaScript зависит от того, как была вызвана эта функция. Я предполагаю, что внутри обработчика теперь это относится к hubProxy или к другому объекту, отличному от collidR.

Если предположить, что весь ваш плагина this относится к collidR (который я очень подозреваю, нет, объяснено в разделе после этого), что вы можете сделать, это сохранить контекст этого объема в другой переменной вне обработчик. Таким образом, вы можете обратиться к контексту внешней области с помощью этой переменной:

// Saving this scope's context 
var that = this; 

hubProxy.on('registrationComplete', function (username, hasChanges) { 

    // access _currentUser via the saved context 
    that._currentUser = username; 

}); 

Однако, я должен предупредить вас об использовании this.Предполагая, что вы создаете плагин, вы назовете его как $.collidR({..}). В этом случае внутри функции будет ссылаться на $ (что я предполагаю jQuery) и you are attaching some property to the library. Встраивание значений, связанных с плагинами, в глобальную библиотеку рискованно, так как могут возникнуть столкновения.

Я предлагаю вам сохранить его внутри локальной переменной/объекта.

+0

Yup, в основном' this' внутри функции ссылается на контекст функции ... –

+0

Спасибо @ Джозеф-Мечтатель ... это имеет смысл для этой старой загрузки C#. :) Итак, не возможно ли тогда получить доступ к свойству экземпляра, а не к методу, из области действия обработчика? Или есть способ вернуть значение локальной переменной из свойства getter? – MisterJames

+2

@MisterJames Вы можете получить доступ к свойству экземпляра, но вам нужно помнить, что JavaScript имеет область функционального уровня, а не область уровня блока. Таким образом, внутри обработчика область - это сам обработчик, поэтому «этот» указывает на этот обработчик, а не на его контейнер. Если вы хотите имитировать инкапсуляцию с помощью JavaScript, я предлагаю прочитать статью Бен-Черри о шаблоне модуля. Поверьте мне, это стоит того. Если вы находитесь на его странице, тоже прочитайте о подъеме :) –

Смежные вопросы