繁体   English   中英

范围函数外部修改了AngularJS变量,它应该无法访问

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

我在任何角度范围(甚至不在控制器之内)中都声明了一个函数(名为“ insertTstData”),当我从控制器(名为“ remark”)中的另一个函数(名为“ save”)调用它时,它进行了修改局部变量,并且更改将反映到范围内的变量以及具有相同内容的所有其他变量(甚至包括那些未以任何方式与其连接的变量!)。

这太荒谬了,我什至不知道如何在不告诉您整个流程的情况下进行解释。

因此,首先,我使用$ 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"}

现在,我在“ remark”控制器中有一个按钮,它调用函数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 =要备注)并返回响应:

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!

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

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

这就是变量的浅表副本与深表副本之间的区别。 在javascript中,总是通过引用(浅拷贝)对对象 (不是原始类型)进行简单分配,这意味着例如

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

rem将保留对对象注释的引用,并且对注释字段的每次更改都将反映rem的更改,反之亦然。 如果要创建两个不同的对象(深复制),则应使用angular.copy

var rem = angular.copy(remarks)

这样,两个变量将对内存中的两个不同区域(即两个不同的对象)持有两个不同的引用。

在此处输入图片说明

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

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

按照此链接在js中创建对象的克隆

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM