2015-08-22 2 views
0

Я работаю в Угловом. Я создал простой сервис, чтобы проиллюстрировать проблему, которую я вижу. Когда кто-то вызывает метод setProfile для этой службы, моя цель - установить «профиль» в новый литерал объекта, который содержит новые значения свойств. Однако, когда я это делаю, не появляется, что пользователи этой службы могут видеть обновления. Другими словами, они видят старый объект «профиль», а не новый. Однако, если я просто обновляю отдельные свойства вместо того, чтобы присваивать «профиль» новому литералу объекта, они прекрасно видят обновления. Я очень смущен.Обнаруживаемый объект углового обслуживания не обновляется?

Этот код работает (то есть после того, как метод setProfile называется, потребители увидят обновленные значения):

(function() { 
angular.module('myApp').factory('myService', function() { 

    var profile = { 
     firstName: '', 
     lastName: '' 
    }; 

    var setProfile = function (firstName, lastName) { 
     profile.firstName = firstName; 
     profile.lastName = lastName; 
    }; 

    return { 
     setProfile: setProfile, 
     profile: profile 
    } 
}); 
}()); 

Но это не работает (то есть, когда я назначить профиль на новый объект буквальным, потребители делают не увидеть новый объект):

(function() { 
angular.module('myApp').factory('myService', function() { 

    var profile = { 
     firstName: '', 
     lastName: '' 
    }; 

    var setProfile = function (firstName, lastName) { 
     profile = { 
      firstName: firstName, 
      lastName: lastName 
     }; 
    }; 

    return { 
     setProfile: setProfile, 
     profile: profile 
    } 
}); 
}()); 

Вот пример того, как услуга может быть использована:

module.run(['$rootScope', 'currentUser', function ($rootScope, currentUser) { 
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { 
    debugger; 
    if (!currentUser.firstName == 'test') { 
     return; 
    } 
}); 
}]); 

ответ

1

Ожидается, что потребители profile имеют ссылку на исходный объект, который создается. Поэтому, если вы обновляете объект через profile.firstName = 'bob', вы обновляете один и тот же объект. Однако, когда вы устанавливаете профиль через profile = {firstname: 'bob'}, вы создаете совершенно новый объект, когда используете фигурные скобки, а все пользователи первого объекта профиля не знают о новом.

Один из способов обойти это с помощью $watch, но, как правило, лучше избегать $watch, если вы можете из соображений удобства.

Что-то еще нужно иметь в виду, что все угловые фабрики/службы - это синглтоны. Поэтому, когда вы новичок в Angular, вы можете ожидать, что новый currentUser вводится каждый раз, когда ваш контроллер запускается, когда на самом деле все инъекции ссылаются на один и тот же экземпляр currentUser.

+0

Итак, переменные указывают на литералы объектов, указывающие на ссылку или значение? Если бы это было по значению, это имело бы смысл, иначе это не так. Потому что, если это по ссылке, это означает, что моя фабрика вернула объект, у которого есть свойство профиля, которое ссылается на внутреннее свойство, которое ссылается на литерал объекта. Поэтому обновление объекта внутреннего профиля к новому объекту будет просто обновлять ссылку. Я что-то упускаю? – spoof3r

+0

Оба;) Возможно, это будет иметь больше смысла: http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – Ryan

+0

Вау, у меня не было идея! Как я использовал JS так долго, не зная об этом? Огромное спасибо!!! – spoof3r

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