4

I recently 'discovered' that Javascript is a "Call by sharing" (wikipedia explanation) language, meaning that in essence, everything is passed by value however the original contents of an object can still be changed. A quick example:

function changeObjectProperties(obj) {
    obj.p = 20;
}

var obj = { p: 10; }
changeObjectProperties(obj);
console.log(obj.p); // will print 20; it's changed!

This made me wonder if this can be used within Angular to 'watch' variables without using $scope.$watch. The following works.

controllers.js:

.controller('Listener', function($scope, UserService) {
    $scope.user = UserService.getUser();
})

.controller('Changer', function($scope, UserService) {

    // let's imagine the UI has some button that changes the e-mailadres
    $scope.buttonClick = function() {
        UserService.setEmail('foo@bar.com');
    }
});

services.js:

.factory('UserService', function() {
    var user = {
        name: 'Foo',
        email: 'example@example.com'
    };

    return {
        getUser: function() { return user; }
        setEmail: function(email) { user.email = email; }
    };
});

The $scope.user variable within the Listener controller is updated when the user clicks the button within the Changer controller. This change is visible would this variable be displayed in the HTML.

The most obvious pitfall of course is that the object itself can not be changed, as the object reference is then changed and the Listener controller is listening to the wrong reference.

I've searched around to find if this is being done and if its considered good coding. I haven't been able to find anything, possibly because I don't know the correct terms to use. So, is this technique actively being used? Is it considered a good practice or is there some pitfall I'm not aware of?

Ssander
  • 706
  • 7
  • 10
  • What technique do you mean? And where do you see a connection to `$watch`? – a better oliver Jan 26 '15 at 11:23
  • The 'technique' of 'watching' a variable as shown above. The e-mailadres change performed by the `Changer` controller is picked up by the `Listener` controller. This would typically be done using $scope.$watch, but apparently it's also possible without. – Ssander Jan 26 '15 at 11:26
  • I see. Well, the controller **doesn't know** that the e-mail address has changed. That's what `$watch` is for: To get informed. – a better oliver Jan 26 '15 at 11:30
  • a) you could $watch for service variable, but I don't understand why do you need to user getUser() instead of direct link to user object? b) if you need to change something in service — I prefer to send signal and not use watch here – syabro Jan 26 '15 at 11:31
  • I can think of two advantages compared to $watch or using broadcasting. First, this method requires less code. Second, I can imagine improved performance as watching/broadcasting contains a (very slight, of course) overhead. – Ssander Jan 26 '15 at 11:40
  • Possible duplicate of [Using $watch without $scope ( controller as syntax)](http://stackoverflow.com/questions/28344131/using-watch-without-scope-controller-as-syntax) – Léo Lam Dec 27 '15 at 15:21

1 Answers1

0

You can certainly employ the base language to avoid excessive watches. Keep in mind there is no way to avoid watch altogether, because watch is fundamentally how Angular tracks the model. In other words, if you do nothing else, putting something on scope is going to cause Angular to watch it so they it knows when to update the rendered UI. This is the essence of the digest loop. To the extent you can manage your internal communication around the way this digest loop operates, you can reduce or eliminate the overhead of extraneous watchers.

So in essence you can use a JavaScript-first approach to coordinate state and internal object transitions and avoid explicit watchers because Angular will pick up the changes via its own watches that are part of the digest loop.

I think what you are talking about is in line with what I wrote about in my 2nd most common mistake AngularJS developers make, which is abusing $watch: http://csharperimage.jeremylikness.com/2014/11/the-top-5-mistakes-angularjs-developers_28.html

Jeremy Likness
  • 7,531
  • 1
  • 23
  • 25