范围外功能修改了它不应该能够访问的AngularJS变量

时间:2016-10-20 09:27:25

标签: javascript angularjs

我在任何角度范围之外声明了一个函数(名为“insertTstData”)(它甚至不在控制器内部或任何东西),当我从控制器内部的另一个函数(名为“save”)调用它时(名为“remark”) ,它会修改一个局部变量,并且变化会反映回范围内的变量以及具有相同内容的所有其他变量(即使是那些没有以任何方式连接到它的变量!)。

这太荒谬了,我甚至不知道如何解释它而不告诉你整个流程。

所以,首先我使用$ http服务来获取JSON配置文件并创建一个范围变量来存储它(我们现在位于“主”控制器中,它是“备注”控制器的父节点,其中发生了错误):

 $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
});

这些变量是对象数组,但为简单起见,我们说它们是具有两个属性的对象:

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

现在,我在“备注”控制器中有一个按钮,它调用函数save并将$ scope.remark传递给它:

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

这里的函数保存在“备注”控制器的范围内(其中注入了“主”范围):

$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!
}

现在,让我们看一下导致错误的功能(记住,它在任何控制器/范围/之外)。 所有函数都根据其他两个参数更改局部变量(set = to remarks)并返回响应:

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!

我完全确定这是它发生的地方,并且这些变量在代码中的任何其他地方都没有改变(昨天调试了几个小时都无济于事)。

我做错了什么?由于我不知道的一些奇怪的机制,它们都是指向相同值的指针吗?

3 个答案:

答案 0 :(得分:1)

这是变量的浅拷贝和深拷贝之间的区别。 在javascript中,一个简单的对象(不是原始类型)的赋值总是通过引用(浅拷贝)来实现,这意味着例如

var remarks = {"p1":"PROP ONE", "p2": "PROP TWO"}
var rem = remarks; //the assignment

rem将保留对对象备注的引用,对备注字段的每次更改都将反映对rem的反应和反之。 如果你想创建两个distint对象(深层复制),你应该使用angular.copy

var rem = angular.copy(remarks)

这样两个变量将对内存中的两个差异区域保持两个不同的引用,从而产生两个不同的对象。

enter image description here

答案 1 :(得分:0)

当您创建变量rem(var rem = remark)时,javaScript会创建对原始对象的引用,而不是复制它。因此,即使您修改了rem,它也会在父对象中进行更改。

我建议你使用clone()方法来创建一个重复的对象。

按照此link进行操作,以便在js

中创建对象的克隆

答案 2 :(得分:0)

您还可以使用angular.copy(remarks)创建对象的深层副本,该副本可以是对象或数组。