fulvaz
V2EX  ›  问与答

为什么不要使用 for...in

  •  
  •   fulvaz · May 24, 2018 · 4998 views
    This topic created in 3088 days ago, the information mentioned may be changed or developed.

    吃完晚饭休息, 随便发点东西

    之前半夜无聊发了点东西, 关于如何优雅地遍历对象 /t/456374

    楼下说使用 for...in 遍历对象的 key

    然而 for...in 的前提是, 你需要保证 Array 的原型没有被改变过.

    为啥? 因为 for...in 会遍历所指定对象全部 enumerable, 如果说你使用的某个库重写了 Array 的原型, 那么遍历的结果就会很奇怪了, 比如说

    Array.prototype.val = 123;
    
    obj = {1: 'a', 2: 'b'}
    
    for (const key in Object.keys(obj)) {
    	console.log(key);
    }
    
    

    上面代码的结果是 0, 1, val, 所以使用 for...in 必须要加 hasOwnProperty.

    不然就乖乖用 forEach.

    多说一句, 正常情况自己是不会重写 Array 的原型的, 但是你不能保证你用的第三方库没使用这种黑魔法.

    再多说一句, 如果重写某个非 enumerable 的属性, 那么该属性还是 enumerable 的, 如 Array.forEach = something, for...in 还是无法遍历的.

    Supplement 1  ·  May 24, 2018
    大意了!!! 业务写迷糊了

    准确的 demo 是

    ```
    Object.prototype.val = 123;

    obj = {1: 'a', 2: 'b'}

    for (const key in obj) {
    console.log(key);
    }
    ```

    原文也应该是, 不知道啥库把 Object 的原型给改了

    嗨呀, 好气, 装逼失败
    15 replies  •  2018-05-25 09:02:34 +08:00
    iloahz
    iloahz
    May 24, 2018 via Android
    1
    不应该是不要改原生类型的原型么。。。
    murmur
    murmur
    May 24, 2018
    2
    我也在想,动不动搞自己类数组出来是图个啥
    fulvaz
    fulvaz
    OP
    May 24, 2018
    3
    @iloahz 你不能保证你用的库不改呀
    Pastsong
    Pastsong
    May 24, 2018❤️1
    4
    @fulvaz 可以保证这种库我不用
    murmur
    murmur
    May 24, 2018
    5
    看错了,不过我记得 array.prototype 扩展的方法被遍历出来是 IE 专属错误?

    Array.prototype.val = 123;

    obj = {1: 'a', 2: 'b'}

    for (var key in obj) {
    console.log(key);
    }

    这个输出 1 2 没有 val

    看来会的越多越容易出麻烦 当然写 var 是在 ie 做兼容写顺手了 没用 object.keys 而已
    yushiro
    yushiro
    May 24, 2018 via iPhone
    6
    ES6 里面用 for of,专门解决这个问题的
    broker
    broker
    May 24, 2018
    7
    for in 和 in operator 在一起时候会报错~

    for (let a = b in c; false;); // does not parse

    for (let a = (b in c); false;); // parses fine

    另一个就是定义 enumerable

    Boolean.prototype.foo = 'bar';

    for (let a in ('' in {})) {
    console.log(a);
    } // prints 'foo'
    des
    des
    May 24, 2018 via Android
    8
    for (const key in Object.keys(obj))

    ???
    写错了吧?
    Biwood
    Biwood
    May 24, 2018 via Android
    9
    假如需要用 return 中断循环操作怎么办? forEach 无法中断吧。另外,修改原生对象的原型这种问题应该在调试的时候就能被发现,出现几率较低,可以忽略。
    des
    des
    May 24, 2018 via Android
    10
    @Biwood 可以用 catch,2333
    Garwih
    Garwih
    May 24, 2018
    11
    @Biwood #9 可以用 every()
    AV1
    AV1
    May 25, 2018 via Android
    13
    @Biwood
    some()、every()
    wengjin456123
    wengjin456123
    May 25, 2018
    14
    是因为会遍历到原型链上的?
    wengjin456123
    wengjin456123
    May 25, 2018
    15
    一般考虑清楚就可以自由选择了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1670 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 05:03 · PVG 13:03 · LAX 21:03 · JFK 00:03
    ♥ Do have faith in what you're doing.