sz tech sz tech - 3 months ago 11
AngularJS Question

What's the difference between angular.equals and _.isEqual?

I mean is there any difference in performance? Which one is able to make the best deep comparison? Sometimes angular's equals function is not able to find every difference.

I have also noticed, that the angular version of this function is not checking the '$$hashKey' key.

Answer

They basically act the same by comparing the values itself and all inner properties. Performance is also close to being the same, at least this will be a difference in 100-200 ms for 10000 elements. I have created small tests suite, warning: your browser page will freeze for few seconds when you run code snippet. I'm not totally sure is this correct way to measure performance so feel free to suggest better ways.

angular
.module("comparsion", [])
.controller("ComparsionCtrl", function($scope) {
  var testCases = 10000;
  
  console.time("underscore");
  for(var i = 0; i < testCases; i++) {
    var obj = createRandomObj(5, true);
    var obj1 = createRandomObj(5, true);
    _.isEqual(obj, obj1);
  }
  console.timeEnd("underscore");
  
  console.time("angular");
  for(var i = 0; i < testCases; i++) {
    var obj = createRandomObj(5, true);
    var obj1 = createRandomObj(5, true);
    angular.equals(obj, obj1);
  }
  console.timeEnd("angular");
  
  // Random object generator from http://stackoverflow.com/questions/2443901/random-object-generator-in-javascript
  function createRandomObj(fieldCount, allowNested)
{
    var generatedObj = {};

    for(var i = 0; i < fieldCount; i++) {
        var generatedObjField;

        switch(randomInt(allowNested ? 6 : 5)) {

            case 0:
            generatedObjField = randomInt(1000);
            break;

            case 1:
            generatedObjField = Math.random();
            break;

            case 2:
            generatedObjField = Math.random() < 0.5 ? true : false;
            break;

            case 3:
            generatedObjField = randomString(randomInt(4) + 4);
            break;

            case 4:
            generatedObjField = null;
            break;

            case 5:
            generatedObjField = createRandomObj(fieldCount, allowNested);
            break;
        }
        generatedObj[randomString(8)] = generatedObjField;
    }
    return generatedObj;
}

// helper functions

function randomInt(rightBound)
{
    return Math.floor(Math.random() * rightBound);
}

function randomString(size)
{
    var alphaChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var generatedString = '';
    for(var i = 0; i < size; i++) {
        generatedString += alphaChars[randomInt(alphaChars.length)];
    }

    return generatedString;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<div ng-app="comparsion">
  <div ng-controller="ComparsionCtrl"></div>
</div>