6

Let's say I have to store customer information, and to manage two-way binding I'll use $scope here. So my doubt here is, which approach is better?

$scope.firstname = "foo";
$scope.lastname = "bar";
$scope.cellno = "1234567890";
$scope.email = "foobar@example.com";

OR

$scope.customerDetailsObj = {};
$scope.customerDetailsObj.firstname = "foo";
$scope.customerDetailsObj.lastname = "bar";
$scope.customerDetailsObj.cellno = "1234567890";
$scope.customerDetailsObj.email = "foobar@example.com";`

I've been wondering about this because I have a large angular application and sometimes the scope watchers count goes beyond 1500. I'm using a chrome extension to see watchers count.

Please share your views. Thank You.

TheCleverIdiot
  • 412
  • 4
  • 19
  • 1
    This may help: https://stackoverflow.com/questions/18128323/if-you-are-not-using-a-dot-in-your-angularjs-models-you-are-doing-it-wrong – Rameez Raja Nov 20 '18 at 08:10
  • 1
    @RameezRaja The answer there is true for *readability* and code structure management, but performance is another issue – CertainPerformance Nov 20 '18 at 08:41
  • Yes, my concern is about the performance. – TheCleverIdiot Nov 20 '18 at 10:54
  • I doupt that fixing this will freatly boost perfomance... Start with measuring your digest (e.g. angular.element(document).injector().invoke(['$rootScope',function($rootScope) { var a = performance.now(); $rootScope.$apply(); return performance.now()-a; }])) – Petr Averyanov Nov 20 '18 at 12:17
  • 1
    Whether a watcher is watching a property of $scope or a property of a scope object, it is still performing a watch function. The watch count will be the same. The name of the item being watched is only parsed once, when it is added the watch list. Look elsewhere to improve performance. – georgeawg Nov 20 '18 at 12:33
  • Property lookups are somewhat "expensive" in JavaScript. `a.b` will resolve faster than `a.b.c`. Whether or not it has a noticeable impact on performance would have to be tested in practice. – plalx Nov 22 '18 at 20:40
  • Thank you, everyone. I'm somewhat sure about objects hierarchy boosting performance better than the variables. But I'm not able to come to any conclusion because the amount of code we have in our application, one has to seat aand spend a large amount of time to figure out which property is used and where it is. P.S I'm new to this project and the watchers' count has caught my attention. – TheCleverIdiot Nov 27 '18 at 12:02
  • 1
    check this out https://stackoverflow.com/questions/8789969/javascript-performance-multiple-variables-or-one-object – holydragon Nov 28 '18 at 09:09
  • Thanks @holydragon, that helped :) – TheCleverIdiot Nov 28 '18 at 09:27

2 Answers2

4

In my opinion and as-per angularjs guide first approach (binding to properties directly) will be more efficient. Excerpt from the guide:

Dirty checking can be done with three strategies: By reference, by collection contents, and by value. The strategies differ in the kinds of changes they detect, and in their performance characteristics.

  • Watching by reference (scope.$watch (watchExpression, listener)) detects a change when the whole value returned by the watch expression switches to a new value. If the value is an array or an object, changes inside it are not detected. This is the most efficient strategy.
  • Watching collection contents (scope.$watchCollection (watchExpression, listener)) detects changes that occur inside an array or an object: When items are added, removed, or reordered. The detection is shallow - it does not reach into nested collections. Watching collection contents is more expensive than watching by reference, because copies of the collection contents need to be maintained. However, the strategy attempts to minimize the amount of copying required.
  • Watching by value (scope.$watch (watchExpression, listener, true)) detects any change in an arbitrarily nested data structure. It is the most powerful change detection strategy, but also the most expensive. A full traversal of the nested data structure is needed on each digest, and a full copy of it needs to be held in memory.

enter image description here

Dipen Shah
  • 25,562
  • 1
  • 32
  • 58
1

Talking only about performance, I think option 1 (having plain variables) it's more efficient.

Watching plain properties

the $watch() function, by default only checks object reference equality. So within each $digest it will check to see if the new and old values pointing to the same object.

Watching objects and arrays

If you want to $watch() an object, you have to switch to the deep watch and that means that within each $digest, it will check the whole tree to see if the structure or values are changed. So, bigger the object, more expensive the check.

$watchGroup(), an alternative to objects/array watchers

If you have a group of related properties like ie a person (name, surname, age), you could define it like plain properties, and use $watchGroup(), that works on the same way like a common $watch() but taking a list of properties to watch rather than one.

DobleL
  • 3,808
  • 14
  • 20