【问题标题】:(Deep?) copy Map in JavaScript [duplicate](深?)在JavaScript中复制地图[重复]
【发布时间】:2020-12-01 09:26:32
【问题描述】:

如何将地图对象深度复制到另一个地图?我正在尝试使用 ES6 方法,但这会返回 Map(0){} 空对象。我的第一次尝试是将地图对象发送给函数并将其分配给此类中的新值。但是在next() 方法上,我从这个映射中删除了一个属性,并在unit test 文件中删除了这个更改映射

creatureTurnQueue.js

    export default class CreatureTurnQueue {
    constructor() {
        this.creatureMap = new Map();
        this.creatureArray = [];
        this.observersArray = [];
    }
    initQueue(list = {}) {
        this.creatureMap = Object.assign({}, list)
        this.creatureMap = list //<=old method

        list.forEach(val => this.creatureArray.push(val));
    }
    getActiveCreature() {
        let [first] = this.creatureArray.filter(el => el);
        return first;
    }
    next(list = {}) {
        this.creatureMap.delete(this.creatureMap.keys().next().value);
        if (this.creatureMap.size == 0) {

            this.notifyObserver();
            this.initQueue(list);
            return true;
        }
    }
    addObserver(_observer) {
        this.observersArray.push(_observer)
    }
    removeObserver(_observer) {
        this.observersArray.pull(_observer)
    }
    notifyObserver() {
        this.observersArray.forEach(item => item.resetCounterAttack())
    }
}

creatureTurnQueueTest.js

import Creature from "../creature.js";
import CreatureTurnQueue from "../creatureTurnQueue.js";
import Point from './../point';

export default class CreatureTurnQueueTest {
    queueShoulChangeActiveCreature() {
        let creatureTurnQueue = new CreatureTurnQueue();

        let creture1 = new Creature("aaaa", 1, 1, 1, 1);
        let creture2 = new Creature("bbbb", 1, 1, 1, 1);
        let creture3 = new Creature("cccc", 1, 1, 1, 1);

        let point1 = new Point(1, 0)
        let point2 = new Point(2, 0)
        let point3 = new Point(3, 0)

        let creatureMap = new Map();
        creatureMap.set(point1, creture1);
        creatureMap.set(point2, creture2);
        creatureMap.set(point3, creture3);

        creatureTurnQueue.initQueue(creatureMap);
        console.log("~ creatureMap", creatureMap) <= map have 2 elements
        creatureMap.forEach(item => { <= creatureMap return 2 elements becouse this one value is removed
            if (item !== creatureTurnQueue.getActiveCreature()) {
                console.log("~ item", item)
                console.log("~ creatureTurnQueue.getActiveCreature()", creatureTurnQueue.getActiveCreature())
                throw `Exception: => Kolejka nie dziala poprawnie zwracana aktywna creatura jest inna`;
            }
            if (creatureTurnQueue.next(creatureMap)) {
                throw `Exception: => Kolejka nie dziala poprawnie w momecie wywolania funkcji next()`;
            }
        });
    }
}

类的其余部分 点.js

export default class Point {
    constructor(_x, _y) {
        this.x = _x;
        this.y = _y;
    }
}

creature.js

import CreatureStatistics from "./creatureStatistics.js";

export default class Creature {
    constructor(_name, _attack, _armor, _maxHp, _moveRange) {
        this.stats = this.createCreature(_name, _attack, _armor, _maxHp, _moveRange);
        this.stats.currentHp = this.stats.maxHp;
        this.stats.wasCounterAttack = false;
    }
    createCreature(_name, _attack, _armor, _maxHp, _moveRange) {
        return new CreatureStatistics(
            _name || "Smok",
            _attack || 1,
            _armor || 1,
            _maxHp || 100,
            _moveRange || 10
        );
    }
    setDefaultStats() {
        // this.stats.wasCounterAttack == true ? this.stats.wasCounterAttack = false : this.stats.wasCounterAttack = true
        this.stats.currentHp = this.stats.currentHp != undefined ? this.stats.currentHp : this.stats.maxHp;
    }
    // popraw counter atack
    attack(_defender) {
        _defender.setDefaultStats();
        this.setDefaultStats();

        if (_defender.isAlive()) {
            _defender.stats.currentHp = this.calculateDamage(_defender);
            if (_defender.isAlive() && !_defender.stats.wasCounterAttack) {
                _defender.stats.wasCounterAttack = true;
                this.stats.currentHp = _defender.calculateDamage(this);
            }
        }
    }
    calculateDamage(attackedCreature) {
        return attackedCreature.stats.currentHp - this.stats.getAttack() + attackedCreature.stats.getArmor() > attackedCreature.stats.getMaxHp()
            ? attackedCreature.stats.currentHp
            : attackedCreature.stats.currentHp - this.stats.getAttack() + attackedCreature.stats.getArmor();
    }
    isAlive() {
        if (this.stats.currentHp > 0) {
            return true;
        }
    }
    getCurrentHp() {
        return this.stats.currentHp;
    }
    resetCounterAttack() {
        this.stats.wasCounterAttack = false;
    }
    canCounterAttack() {
        return !this.stats.wasCounterAttack
    }

}

creatureStatistics.js

export default class CreatureStatistics {
    constructor(_name, _attack, _armor, _maxHp, _moveRange) {
        this.name = _name;
        this.attack = _attack;
        this.armor = _armor;
        this.maxHp = _maxHp;
        this.moveRange = _moveRange;
    }
    getName() {
        return this.name;
    }
    getAttack() {
        return this.attack;
    }
    getArmor() {
        return this.armor;
    }
    getMaxHp() {
        return this.maxHp;
    }
    getMoveRange() {
        return this.moveRange;
    }
}

【问题讨论】:

  • 其实Object.assign是一个浅拷贝
  • 好的,现在问题好多了。
  • 您不想深度复制您的地图。你只需要复制它。

标签: javascript


【解决方案1】:

该地图实际上是来自unit test 脚本的creatureMap 的引用。修改类中的映射将修改unit test 中的creatureMap。您可以尝试创建一个新 Map 并复制所有值:

// Start class CreateTurnQueue
initQueue(list = {}) {
   
   const newMap = new Map();
   
   // Both Object and Map has entries method although the order is different
   const iterator = list.entries();
   
   for(const item of iterator) {
      const [point, creature] = item;
      newMap.set(point, creature);
      this.creatureArray.push(creature);
   }
   this.creatureMap = newMap;
   
}
// End class CreateTurnQueue

现在您没有从 unit test 脚​​本中引用 creatureMap 并修改 this.creatureMap 不会影响您作为参数传递给 initQueue 方法的那个。

【讨论】:

  • 没必要把它弄得这么复杂:this.creatureMap = new Map(list); this.creatureArray = Array.from(list.values());
猜你喜欢
  • 2012-07-03
  • 2015-05-06
  • 2020-03-25
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 2014-06-28
相关资源
最近更新 更多