我在任何角度范围之外声明了一个函数(名为“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!
我完全确定这是它发生的地方,并且这些变量在代码中的任何其他地方都没有改变(昨天调试了几个小时都无济于事)。
我做错了什么?由于我不知道的一些奇怪的机制,它们都是指向相同值的指针吗?
答案 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)
这样两个变量将对内存中的两个差异区域保持两个不同的引用,从而产生两个不同的对象。
答案 1 :(得分:0)
当您创建变量rem(var rem = remark)时,javaScript会创建对原始对象的引用,而不是复制它。因此,即使您修改了rem,它也会在父对象中进行更改。
我建议你使用clone()方法来创建一个重复的对象。
按照此link进行操作,以便在js
中创建对象的克隆答案 2 :(得分:0)
您还可以使用angular.copy(remarks)
创建对象的深层副本,该副本可以是对象或数组。