for .... in 存在的兼容问题你造吗?

在js中for_in主要是用来遍历对象的可枚举属性,包括原型链上的属性。然而for_in在IE < 9下可能会出现问题。
for_in要出现问题必须满足两个条件:
   1:IE < 9;
   2:某些不可枚举的属性被重写。
在js中当一些不可枚举的属性比如toString被重写后,它会变成可枚举。然而当你碰上了IE<9,这些被重写的属性依旧
是不可枚举无法使用for_in去遍历。那么如何在IE<9的情况下去搜集这些被重写的不可枚举属性。
思路:
  一、先重写一个不可枚举属性并用propertyIsEnumerable去检测是否可枚举来判断是否是IE < 9;
  二、将不可枚举的属性组成数组以待后续遍历;
  三、先拿到对象的原型,constructor属性要单独检测,至于为什么,个人感觉是因为并不是所有对象都有constructor,只有通过构造函数得到的对象才有该属性,检测constructor属性,在排除原型链的情况下判断对象上是否具有constructor属性并且得到的属性数组中
不包含constructor。其他属性,主要是从不可枚举的属性数组中遍历,判断属性数组中是否包含此属性并且该属性属
于该对象并且原型上的该属性不等于该对象上此属性。
underscore.js中给出以下方法。
  一、首先定义hasEnumBug来判断是否是IE<9
    var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');//返回false
  二、然后列出IE<9下不能用for in来枚举的key值集合
    var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
  三、最后搜集方法
    var collectNonEnumProps = function(obj, keys) {
        var nonEnumIdx = nonEnumerableProps.length;
        var constructor = obj.constructor;
        //获得原型,两种情况,构造函数和字面量形式 obj.constructor.prototype 和 obj.__proto__
        var proto = _.isFunction(constructor) && constructor.prototype || ObjProto;
        // `constructor` 属性需要特殊处理
        var prop = 'constructor';
        //对象重写了constructor 并且keys数组不包含constructor
        if (_.has(obj, prop) && !_.contains(keys, prop)) {
            keys.push(prop);
        }
        //遍历nonEnumerableProps数组
        while (nonEnumIdx--) {
            prop = nonEnumerableProps[nonEnumIdx];
            //判断是否重写了不可枚举属性
            //in用来判断一个属性是不是属于一个对象,这个属性可以是原型链上的,也可以是不可枚举属性
            if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
                keys.push(prop);
            }
        }
    };

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值