编程技术文章分享与教程

网站首页 > 技术文章 正文

for-in与不可枚举

hmc789 2024-11-18 13:00:12 技术文章 2 ℃

用for循环遍历对象

var person = {
  name: 'tom',
  age: 29,
  sex: '男'
}

首先有Object.keys()的方法,拿到可迭代(遍历)的私有属性名的集合(数组)

var keys = Object.keys(person);
    for (var i = 0; i < keys.length; i++) {
    console.log(keys[i] + ":" + person[keys[i]]); 
        // 输出: name:tom   age: 29    sex: '男'
}


但如果直接用 for...in 遍历可能会出现缺陷:

for in 典型的缺陷:

var arr = [1, 2, 3, 4];

正常情况:

for (var i in arr) {
  console.log(i);
} //输出 0 1 2 3

正常情况下我们输出的是没问题的;但是

如果你给 Array添加了一个(判断元素是不是存在数组中)的新方法:

Array.prototype.inArray = function () {
  for (var i = 0; i < this.length; i++) {
    if (this[n] === ele) {
    return true;
    }
  }
  return false;
};

然后我们再试试 for...in ,看一看它还好不好使。

for (var i in arr) {
  console.log(i);
}//输出 0 1 2 3 inArray

为什么会多了一个inArray呢?因为它也被遍历出来了。


for...in...会遍历到对象中所有可枚举的属性方法,我们给对象添加的方法默认也是可枚举的;

自己添加的方法怎么样才能不被遍历到呢?

于是我们就用到了 Object.defineProperty ()

这个方法。

该方法允许精确地添加或修改对象的属性。通过赋值操作修改,在枚举对象属性时会被枚举到(for...inObject.keys方法),可以改变这些属性的值,也可以删除这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改(immutable)的。 (摘自:MDN web docs)

此方法有四个属性:

configurable
当且仅当该属性的
configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false
enumerable
当且仅当该属性的
enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false
数据描述符还具有以下可选键值:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined
writable
当且仅当该属性的
writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。 默认为 false
(摘自:MDN web docs)

看了这四个属性,我们就能很开心的解决上面的问题了:

        var arr = [1, 2, 3, 4];
        Array.prototype.inArray = function() {
            for (var i = 0; i < this.length; i++) {
                if (this[n] === ele) {
                    return true;
                }
            }
            return false;
        };
        //解决问题的代码
        Object.defineProperty(Array.prototype, 'inArray', {
            enumerable: false  //不可枚举(即不可遍历)
        })

?
        for (var i in arr) {
            console.log(i);
        } //输出 0 1 2 3 

到此为止我们的问题就解决了!希望能帮助到大家!

Tags:

标签列表
最新留言