帮我在嵌套循环中为对象分配值。
我需要实际调试的代码如下所示:
// Next states
let nextVal = undefined
let nextBoard = undefined
let next_player_value = undefined
shuffle(Board.rowCols).forEach(c => {
shuffle(Board.rowCols[c]).forEach(r => {
if (board[c][r] === undefined) {
board[c][r] = player_state // let's test the current player moving to this location
next_player_value = this.getMinMaxPlayerValue(!player_state)
let minmax = AI.recurseMinMax(next_player_value, board, depth+1)
let value = minmax[0]
if (((player_state===this.getState()) && (nextVal === undefined || value > nextVal)) || // its the AI, and the value increases
((player_state!==this.getState()) && (nextVal === undefined || value < nextVal))) { // its the player, and the value decreases
nextBoard = Object.assign({},board)
nextVal = value
}
board[c][r] = undefined
}
})
})
return [nextVal, nextBoard]
如果您观看调试器,会发生什么情况,那就是它正确地为
nextBoard
分配了不同的电路板位置,但是当它在通往return
语句的途中退出外部块时,nextBoard
会更改。它不会成为undefined
!相反,它成为当前的Board.state
中没有任何新动静(应该存在的动静像其他所有空的木板空间一样处于undefined
状态)。player_state
从未被定义,但是它是recurseMinMax
的参数(这是此代码的包含函数)。实际上,它始终是true
或false
。我无法轻松替换它-我尝试将分配更改为!!player_state
和Object.assign({}, player_state)
。嵌套循环或闭包不是问题。这里有几个例子:
从控制台
> let a; b = {}; keys=[1]; values =[2];
keys.forEach(key => {
values.forEach(value => {
b[key]=value;
a = Object.assign({},b)
})
})
< undefined
> a
< Object {1: 2}
为什么这样不起作用:
损坏的示例(使用数组而不是哈希)
let nextBoard = undefined
[0,1,2].forEach(i =>{
[0,1,2].forEach(j =>{
if (board[i][j] == null) {
board[i][j] = player;
var value = recurseMinimax(board, !player)[0];
if ((player && (nextVal == null || value > nextVal)) || (!player && (nextVal == null || value < nextVal))) {
nextBoard = Object.assign({},board)
nextVal = value
}
board[i][j] = null;
}
})
})
就像我的实际代码中那样中断。
它应该是当前的
Board.state
,但是其中又有一个移动,它被分配给board[i][j] = player;
。现在这是有趣的事情,当我们使用这样的数组时,我可以使它很容易地工作:
工作示例(使用数组而不是嵌套的哈希)
[0,1,2].forEach(i =>{
[0,1,2].forEach(j =>{
if (board[i][j] == null) {
board[i][j] = player;
var value = recurseMinimax(board, !player)[0];
if ((player && (nextVal == null || value > nextVal)) || (!player && (nextVal == null || value < nextVal))) {
nextBoard = board.map(function(arr) {
return arr.slice();
});
nextVal = value
}
board[i][j] = null;
}
})
})
这个很好用。
问题是,我的实际木板不是嵌套数组,而是嵌套哈希:
Board.state = {};
['a','b','c'].forEach(c => {
Board.state[c]={};
[1,2,3].forEach(r => Board.state[r]=undefined)
});
最佳答案
发生这种情况是因为Object.assign({},board)
进行了浅拷贝,即board
中的行将与从Object.assign
返回的值相同。
您应该复制一份完整的副本。
一种怪异的方法是使用JSON
:
nextboard = JSON.parse(JSON.stringify(board));
...尽管这仅在
board
仅包含JSON支持的基本类型时起作用(因此,没有函数,集合,映射等)。有关其他解决方案,请参见How to deep clone in JavaScript
例如this answer这是我自己的手:
function deepClone(obj, hash = new WeakMap()) {
if (Object(obj) !== obj) return obj; // primitives
if (hash.has(obj)) return hash.get(obj); // cyclic reference
var result = Array.isArray(obj) ? []
: obj.constructor ? new obj.constructor() : Object.create(null);
hash.set(obj, result);
if (obj instanceof Map)
Array.from(obj, ([key, val]) => result.set(key, deepClone(val, hash)) );
return Object.assign(result, ...Object.keys(obj).map (
key => ({ [key]: deepClone(obj[key], hash) }) ));
}
...并且一旦有了该功能,就可以执行以下操作:
nextboard = deepClone(board);
函数中的某些功能可能对您无用(例如,对循环引用和
Map
的支持),因此您可以根据需要对其进行简化。关于javascript - 如何在闭包中分配给外部嵌套哈希中的键,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41209595/