深刻理解枚举属性与for-in和for-of

首先要分清什么是可枚举属性,什么是不可枚举属性javascript

1.可枚举属性

在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的。可枚举性决定了这个属性可否被for…in查找遍历到。html

1.1怎么判断属性是否可枚举

js中基本包装类型的原型属性是不可枚举的,如Object, Array, Number等,若是你写出这样的代码遍历其中的属性:java

var num = new Number();
for(var pro in num) {
    console.log("num." + pro + " = " + num[pro]);
}

它的输出结果会是空。这是由于Number中内置的属性是不可枚举的,因此不能被for…in访问到。json

Object对象的propertyIsEnumerable()方法能够判断此对象是否包含某个属性,而且这个属性是否可枚举。数组

须要注意的是:若是判断的属性存在于Object对象的原型内,无论它是否可枚举都会返回false。函数

1.2枚举性的做用

举个例子:性能

Object.prototype.objCustom = function () { };

function Person() {
    this.name = "KXY";
}
Person.prototype = {
    constructor: Person,
    job: "student",
};
 
var kxy = new Person();
Object.defineProperty(kxy, "sex", {
    value: "female",
    enumerable: false
});

则用for in 来遍历的话ui

for(var pro in kxy) {
    console.log("kxy." + pro + " = " + kxy[pro]);
}
// kxy.name = KXY
// kxy.constructor = function Person() {
// this.name = "KXY";
// }
// kxy.job = student
// kxy.objCustom = function () { }

在这个kxy实例对象之中,咱们能够发现咱们能够遍历出四个可枚举属性,这个单纯看的话,很难理解为何会有这四个属性,因而我画了张图,给你们解释下,红色部分表示不可枚举属性,绿色表示可枚举属性。这张图呢若是一看一脸懵逼,你们能够去参考《JavaScript高级程序设计》这本书的原型讲解的那一部分,我以前也发过随笔单独作了原型那一部分的笔记,也能够去翻一翻。this

其中sex不能够枚举是由于设置了enumberle这个属性,而object是由于他是JS基本包装类,因此他的任何属性都不能够被枚举。prototype

咱们for-in的事这个实例,他有protosex这两个属性,sex不行,因此顺着__proto__是往下翻,能够接收到他的原型的constructorjob__proto__其中job能够直接枚举,而后剩下两个constructor__proto__能够接着往下找,constructor是链接着构造函数,构造函数里有一个name因此将他输出,而后这一条路结束了。而后看原型的__proto__就是Object,由于他是JS的基本包装类,因此他里面的任何自带属性都不能被枚举,而咱们自定义的objCustom方法是能够被枚举的,他不是自带的属性。因此综上所述,最后迭代出四个属性。因此for-in的大体过程就是这样。

1.3 Object.keys() 和JSON.stringify()

这两个方法也能够帮助咱们判断属性是否能够枚举。

首先 Object.keys() 这个方法是专门用来返回一个对象的全部可枚举属性的字符串的。因此用它能够达到和for-in近似的效果。惟一不一样的就是不能取到全部属性的值。

而JSON.stringify()这个只能stringify可枚举属性的值,若是不可枚举的是不会显示的。

2.for-in和for-of

2.1for-in

上面讲了那么多,感受for-in讲的已经差很少了,for-in的主要做用就是迭代一个对象里的可枚举属性。

用法是:

for (variable in object) {...}
  • variable

    在每次迭代时,将不一样的属性名分配给变量

  • object

    被迭代枚举其属性的对象。

实例:

<script>
    function Person() {
      this.name = "KXY";
    }

    var kxy = new Person();
    for (var pro in kxy) {
      kxy[pro] = 'yxk'
      console.log("kxy." + pro + " = " + kxy[pro]);
    }
    console.log(kxy);
  </script>

结果:

值得一提的是,for-in 和for-of在迭代的过程当中若是修改了属性的值,会直接做用在对象上。可是不推荐这么作由于这里并不保证是否一个被添加的属性在迭代过程当中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除以前被访问。

另外for-in不推荐去迭代一个数组,由于数组索引只是具备整数名称的枚举属性,而且与通用对象属性相同。不能保证for ... in将以任何特定的顺序返回索引。

2.1.1 hasOwnProperty()

asOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具备指定的属性(也就是是否有指定的键)

最开始的枚举属性的例子for-in不只会将实例的属性迭代,并且会将原型上的属性一并迭代,若是只想迭代自身属性的话,那么就要配合上hasOwnProperty()这个属性了。

实例:

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i);
  }
}
 // 结果:
 // logs 0, 1, 2, "foo"

for (let i in iterable) {
  console.log(i); 
}

// 结果:
// logs 0, 1, 2, "foo", "arrCustom", "objCustom"

2.2 for-of

for...of语句在可迭代对象上(包括Array,Map,Set,String,TyedArray,arguments对象等等)上建立一个迭代循环,调用自定义迭代钩子,并为每一个不一样属性的值执行语句

用法

for (variable of iterable) {
    //statements
}
  • variable

在每次迭代中,将不一样属性的值分配给变量。

  • iterable

被迭代枚举其属性的对象。

for-of一样能够直接修改迭代对象的值,并且不像for-in会去迭代可枚举属性的值。

For-of除了遍历最基本的数组,还常常用在迭代字符串上。

具体更多的方法就参考文档吧,for-of感受并无什么难点。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of
更多的遍历数组能够看我上一篇随笔:http://www.javashuo.com/article/p-dezyiili-my.html

就写这么多吧,只是很简单的总结,若是有什么问题请你们指正。

相关文章
相关标签/搜索