V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
teslayun
V2EX  ›  JavaScript

被方括号引用搞懵逼了

  •  
  •   teslayun · 2021-10-28 15:56:47 +08:00 · 2806 次点击
    这是一个创建于 904 天前的主题,其中的信息可能已经有所发展或是发生改变。
    var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};
    object[foo] = 'value';
    console.log(object[bar]);
    

    原文:上述的代码的输出也是 "value",由于对象 foo 和 bar 都会被转成相同的字符串。在 SpiderMonkey JavaScript 引擎中,这个字符串是 "[object Object]"。

    这是啥原理。。。

    查方括号引用的时候看见的一个例子, https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors

    15 条回复    2021-10-28 18:44:34 +08:00
    murmur
        1
    murmur  
       2021-10-28 15:59:15 +08:00
    不是,这东西除了面试,真的有人用么,想输出就老老实实的自己写序列化,或者就 json.stringify ,java 开发也没人直接把 object 扔 logger 里打印把
    murmur
        2
    murmur  
       2021-10-28 16:00:26 +08:00
    哦,记错考点了,你这个得用 WeakMap ,这个 key 是可以用对象的
    Kasumi20
        3
    Kasumi20  
       2021-10-28 16:01:10 +08:00
    什么什么意思,因为你访问的是 foo.[object Object] 啊
    yaphets666
        4
    yaphets666  
       2021-10-28 16:01:46 +08:00
    原理就是引擎内部对这种特殊情况做了处理呗,js 里面好多类似的。
    对象和数组不是一回事。数组的 a 是指向 a[0],但是对象没有这种逻辑啊。
    mxT52CRuqR6o5
        5
    mxT52CRuqR6o5  
       2021-10-28 16:01:50 +08:00   ❤️ 1
    object 的 key 是 string ,所以 object[foo]约等于是 object[foo.toString()]
    kevin1
        6
    kevin1  
       2021-10-28 16:03:12 +08:00   ❤️ 1
    对象在用作 key 时被自动转化成了"[object Object]",因为普通对象的 key 只能是 String 。所以其实当你访问 obj[foo]时,实际上是在访问 obj["object Object"]。
    kop1989
        7
    kop1989  
       2021-10-28 16:05:53 +08:00
    你观察 object 的结构就会发现。一个对象的字段名,是可以为[object Object]的,无论是 object[foo]还是 object[bar]你对应的都是 object.[object Object](伪代码)。
    jtwor
        8
    jtwor  
       2021-10-28 16:06:51 +08:00
    6 对的
    teslayun
        9
    teslayun  
    OP
       2021-10-28 16:08:04 +08:00
    @murmur #1, 这种方括号引用还是有用的吧,比如必须使用变量来访问属性的时候
    murmur
        10
    murmur  
       2021-10-28 16:09:27 +08:00
    @teslayun 一般的 map key 是字符串,方括号那个用法不是
    var a = {
    [dynamicKey]: 'value'
    }
    这种写法么
    拿 object 做 key ,要么是 weakmap 的高端用法,要么是开发或者面试故意留的坑
    teslayun
        11
    teslayun  
    OP
       2021-10-28 16:11:55 +08:00
    @kop1989
    @kevin1
    @mxT52CRuqR6o5 明白了,感谢大佬,普通对象的 key 只能是 String ,对象用 key 的时候被 toString()了,那么,上面这个,如果打印 object[object]应该也是一样的输出“value”
    kop1989
        12
    kop1989  
       2021-10-28 16:13:25 +08:00
    @murmur #9 一般情况下就是单纯的留的坑,就跟问 Integer 5 == Integer 5 返回 true 还是 false 一样。反问一句面试官这玩意的用意是什么,对方估计也就是吃瘪或者背个官话。

    @teslayun #10 赵本山:“恭喜你都会抢答了~”
    teslayun
        13
    teslayun  
    OP
       2021-10-28 16:20:17 +08:00
    @murmur 不是哦,比如计算数组中元素出现的次数,弄成对象属性
    const list = ["a", "b", "c", "a", "a"];

    const countedList = list.reduce(function (acc, cur) {
    if (cur in acc) {
    acc[cur]++;
    } else {
    acc[cur] = 1;
    }
    return acc;
    }, {});
    console.log(countedList);

    // {a: 3, b: 1, c: 1}
    tsanie
        14
    tsanie  
       2021-10-28 17:23:28 +08:00   ❤️ 1
    @teslayun 捉一个虫,cur in acc 要写成 acc.hasOwnProperty(cur),否则源数组里一旦有个'constructor', 'toString'之类的元素就要出错辣

    或者{}改成 Object.create(null)
    noe132
        15
    noe132  
       2021-10-28 18:44:34 +08:00   ❤️ 1
    https://262.ecma-international.org/5.1/#sec-11.2.1
    第六步,对属性名是执行了 ToString 内部逻辑的。普通对象 ToString 的结果最后的逻辑是调用了 valueOf ,valueOf 调用了 toString 方法,结果就是一个"[object Object]"字符串。

    如果想让对象作为 key ,建议使用 Map 。Map 可以用对象作为 key 来存储数据。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   918 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 20:18 · PVG 04:18 · LAX 13:18 · JFK 16:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.