![](/img/trans.png)
[英]not able to access $scope object outside a http response callback function in 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.