0

I'm currently in a situation where I need to create a few watches based on the properties of an object.

These properties are used to group functions that depend on the same variable / expression.

While creating the $watch functions in the loop, it seems to well, but when the watches actually execute, only the last property is persisted in the function scope. Which means that for all $watches (which evaluate different expressions), the functions that get executed are the same.

for (var prop in obj) {
    if (obj.hasOwnProperty(prop) {
        $scope.$watch(function() { 
            return evaluateExpression(obj[prop].expression);
        }, function(newVal, oldVal) {
            evaluateDependentExpressions(obj[prop].dependentExpressions);
        }); 
    }
}

Now if my obj variable looks like this:

var obj = {
    'Person.Name': {
        expression: ...,
        dependentExpressions: [...]
    },
    'Person.Age': {
        expression: ...,
        dependentExpressions: [...]
    }
};

Then the function evaluateDependentExpressions is called twice in where the value of prop = 'Person.Age'.

Any help how to solve the function scope problem is greatly appreciated.

plunk

Koen Morren
  • 1,233
  • 2
  • 9
  • 12

1 Answers1

2

This is known problem in JavaScript prop variable is set to last used value in for (var prop in obj), simple workaround is to use IIFE:

for (var p in obj) {
  (function(prop) {
     // your code

     if (obj.hasOwnProperty(prop) {
       $scope.$watch(function() { 
        return evaluateExpression(obj[prop].expression);
       }, function(newVal, oldVal) {
        evaluateDependentExpressions(obj[prop].dependentExpressions);
       }); 
     }
   })(p);
}

Explanation here: JavaScript closure inside loops – simple practical example

Community
  • 1
  • 1
csharpfolk
  • 4,124
  • 25
  • 31