zoukankan      html  css  js  c++  java
  • nodejs以对象做对象的key导致value一直被覆盖

     
    问题描述

    在开发中,实现技能状态的事件监听功能时,将状态对象作为key,存入事件管理器的监听列表,如下图:

     

    image.png

    实现后,运行程序,并没有报错,但是当某个事件发生时,只有一个状态被触发监听,而大多数状态在创建时,就监听了该事件,正确的表现应当是所有监听该事件的状态对象都被触发。

     

    原因分析

    首先判断是状态实现问题,但是每个状态都是继承AbstractState这个父类,并没有重新实现父类的事件监听函数,检查父类监听代码实现,未发现问题。

    代码检查没有发现问题,看着是正常的,但实际效果确实有问题,于是添加打印,在addEventListener之前打印监听列表,addEventListener之后也打印监听列表,

    打印的结果显示,addEventListener之前如果监听列表为空,那么addEventListener之后会成功添加一个监听,但是如果addEventListener之前监听列表有一个监听了,那么addEventListener之后,监听列表只会剩下最新添加的那个监听!这就是问题所在了,但是为什么会出现这种情况呢?为什么新的对象会覆盖旧的?

     

    将本次遇到的问题简单化成如下例子:

    image.png

    可以看到,b实际上一直只有一个key,即'[object Object]'这个字符串,变化的只是value,在JS中,创建对象时,不论以什么类型的值做Key,JS会默认调用toString()方法将该key转成字符串类型,如数字类型:

    image.png

    可以看到key 1 变成了 '1',而当key时对象时,object.toString()的结果只会等于'[object Object]',如下图:

    image.png

    这就是上面为什么b对象永远只会有一个key =  '[object Object]'的原因,JS不支持对象使用toString()方法,即不支持对象以对象做key。

    另外,对象转字符串,JS提供JSON.Stringify()特殊方法。

    解决方案

    鉴于上面的分析结果,如果还是执意想要用状态对象做key的话,可以使用JSON.Stringify(state),但这显得不够优雅,最后的解决方案是在每个状态对象中,增加一个uuid属性,以该uuid作为Key,存入监听列表中。

     

     
  • 相关阅读:
    辗转相除法求最大公约数和最小公倍数
    KMEANS算法
    Extjs RadioGroup中Radio的切换
    B树、B树、B+树、B*树都是什么
    DBSCAN算法的java实现
    SQL 基础:Select语句,各种join,union用法
    Ubuntu 安装中文输入法 fcitx
    Salesforce 主要发展历史
    Pair Programming(结对编程)
    学习笔记 设计模式之装饰者模式
  • 原文地址:https://www.cnblogs.com/yourstars/p/11970572.html
Copyright © 2011-2022 走看看