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,存入监听列表中。

     

     
  • 相关阅读:
    前插法创建带头节点的单链表
    利用Oracle数据库发送邮件
    关于如何给C#中的ListBox控件添加双击事件
    类似QQ表情的功能,包括动态绑定图片
    ASP.NET 缓存技术总结
    VS2008 快捷键大全
    Oracle 中union的用法
    C#找到Excel中的所有Sheetname的方法
    推荐一个学习XPath的网站
    Oracle游标使用大全
  • 原文地址:https://www.cnblogs.com/yourstars/p/11970572.html
Copyright © 2011-2022 走看看