Kitra Kitra - 1 month ago 7
AngularJS Question

Outside of scope function modifies AngularJS variables it should't be able to access

I declared a function (named "insertTstData") outside any angular scope (it's not even inside a controller or anything) and when I call it from another function (named "save") inside a controller (named "remark"), it modifies a local variable and the change gets reflected back to the variable inside the scope and every other variable with the same content (even the ones not connected to it in any way!).

It's so absurd I don't even know how to explain it without telling you the whole flow.

So, first off i use the $http service to get a JSON configuration file and create a scope variable to store it (we're now in the "main" controller, which is the parent of the "remark" one, in which the bug happens):

$http.get(path + 'remarkConfig.json')
.then(function (response) {
//change fields
$scope.remark = response.data; //this variable will get used later on
$scope.dummy = response.data; //this variable will be changed even if not used anymore
});


These variables are array of objects, but for simplicity let's say they're object with two properties:

{"p1":"PROP ONE", "p2": "PROP TWO"}


now, i have a button inside the "remark" controller which calls the function save and passes $scope.remark to it:

<md-button class="amaButton md-raised" ng-click="save(data, remark)" aria-label="save">{{translate.save}}</md-button>


here's the function save inside the "remark" controller's scope (in which is injected the "main" scope):

$scope.save = function (data, remarks) {
console.log($scope.dummy);
console.log($scope.remark);
console.log(remarks);
//all these variables still contain the original values
var originalRemarks = {}; //another dummy variable, just to be sure
originalRemarks.codes = remarks;
//insert TSTs into data, formatting <>-like remarks
var response = insertTstData(data, $scope.tst, remarks); //this is the function which wreaks havoc, I pass to it the variable remarks by value (or at least I thought so)
console.log($scope.dummy);
console.log($scope.remark);
console.log(remarks);
console.log(originalRemarks.codes);
//they ALL changed!
}


Now, let's see the function which causes the bug (remember, it's outside any controller/scope/whatever).
All the function does is changing a local variable (set = to remarks) according to the other two arguments and returns a response:

function insertTstData(data, tst, remarks) {
var rem = remarks;
rem.p1="";
var response={"data": data, "remarks": rem};
return response;
}
//after these function returns, every variable's p1 is set to an empty string!


I'm totally sure this is the point in which it happens and these variables aren't changed ANYWHERE else in the code (debugged it for hours yesterday to no avail).

What am I doing wrong? Are they all pointers to the same value due to some strange mechanic I'm not aware of?

Answer

When ever you create a variable rem (var rem = remark), javaScript creates a reference to the original object, instead of making a clone of it. So, even if you modify rem, it will make the changes in the parent object.

I suggest you to use clone() method, to create a duplicate object.

Follow through this link for creating a clone of an object in js

Comments