使用JavaScript循环更新数组对象属性时遇赋值异常求助
问题分析与解决方案
先帮你拆解下问题根源,再给出修复后的代码:
核心问题原因
你的代码出现「仅最后一个对象的allowedToView1有值」的情况,主要是两个问题叠加导致的:
1. 闭包变量绑定陷阱
你在x.map(function(prop) { ... })里用到的prop变量,因为JavaScript的函数作用域特性,当Promise的异步回调执行时,外层循环的i已经走到了最后一次迭代的值,所有异步回调里的prop都会指向最后一个循环对象,导致前面的资源对象无法匹配到正确的resId。
2. 重复重置数组导致数据丢失
在angular.forEach($scope.listofResource, function(vv) { vv.allowedToView1 = []; ... })这一步,每次Promise回调执行时,你都会把所有资源对象的allowedToView1重置为空数组,然后只给当前处理的资源添加数据。前面循环处理的资源数组会被后面的循环清空,最终只有最后一个资源能保留数据。
修复后的代码
我调整了代码逻辑,解决了上述两个问题:
$scope.listofResource = msg.data; // 提前给每个资源初始化空的allowedToView1数组,避免后续重复清空 $scope.listofResource.forEach(item => { item.allowedToView1 = []; }); // 用forEach遍历资源,避免var带来的闭包陷阱 $scope.listofResource.forEach(resource => { const allowedIds = resource.allowedToView.split(","); // 生成每个用户ID对应的请求Promise const userPromises = allowedIds.map(id => { const requestParams = { allowedId: parseInt(id) }; return ResourceService.getAllowedUsers(requestParams).then(msg1 => { const userInfo = msg1.data[0]; userInfo.resId = resource.Id; return userInfo; }); }); // 等待当前资源的所有用户请求完成后,更新对应数组 Promise.all(userPromises).then(matchedUsers => { // 直接找到当前资源,精准更新数组 const targetResource = $scope.listofResource.find(r => r.Id === resource.Id); if (targetResource) { matchedUsers.forEach(user => { targetResource.allowedToView1.push(user); }); } }); });
关键改进点
- 提前初始化数组:在循环开始前就给每个资源对象创建空的
allowedToView1,避免后续回调清空已有数据。 - 规避闭包陷阱:使用
forEach遍历资源,每次迭代的resource都是独立的块级变量,异步回调能正确绑定到当前资源;如果坚持用for循环,把var i改成let i也能解决作用域问题。 - 精准更新资源:通过
find直接定位目标资源,不用遍历整个数组,既提升效率也避免误操作其他资源的数组。
这样修改后,每个资源的allowedToView1都会正确填充对应的用户信息了。
内容的提问来源于stack exchange,提问作者pryxen
相关产品推荐
相关产品推荐

