美文网首页
js 中 for 和 for in 遍历数组区别及Object.

js 中 for 和 for in 遍历数组区别及Object.

作者: 人总要靠自己_趁年轻去努力 | 来源:发表于2019-11-21 19:03 被阅读0次

    ECMAScript 将对象的属性分为两种:数据属性访问器属性。每一种属性内部都有一些特性,这里我们只要关注对象属性的[[Enumerable]]特性,可以理解为:是否可枚举。
    然后根据上下文环境的不同,我们又可以将属性分为:原型属性实例属性。原型属性是定义在对象的原型(prototype)中的属性,而实例属性就是构造函数实例化后添加的新属性。

    for in 循环

    使用 for in 循环,只遍历对象自身和继承的可枚举的属性。
    虽然 for in 主要用于遍历对象属性,但同样也可以用来遍历数组元素。

    let arr = ['a', 'b', 'c', 'd'];
    for (let i in arr) {
      console.log('索引: ' + i, '值: ' + arr[i]);
    }
    for (let i = 0; i < arr.length; i++) {
      console.log('索引: ' + i, '值: ' + arr[i]);
    }
    // 两种方式都输出:
      // 索引: 0 值: a
      // 索引: 1 值: b
      // 索引: 2 值: c
      // 索引: 3 值: d
    
    

    for 和 for in 遍历数组的区别主要有 3 点:
    1. 如果扩展了 Array,那么扩展的属性会被 for in 输出。

    let colors = ['red', 'green', 'yellow'];
    // 扩展了 Array.prototype
    Array.prototype.demo = function () {};
    for (let i in colors) {
      console.log(i);  // 0 1 2 demo
    }
    // 查看原型的方法[[enumerable]]特性,以 push 方法为例
    console.log(Array.prototype.propertyIsEnumerable('push'));  // false
    console.log(Object.getOwnPropertyDescriptor(Array.prototype, 'push'));  // {value: ƒ, writable: true, enumerable: false, configurable: true}
    // 查看 demo 属性的特性
    console.log(Array.prototype.propertyIsEnumerable('demo'));  // true
    console.log(Object.getOwnPropertyDescriptor(Array.prototype, 'demo'));  // {value: ƒ, writable: true, enumerable: true, configurable: true}
    

    可以看出我们添加的 demo 方法,默认是可以被 for in 枚举出来的。如果不想被其枚举,可以使用 Es5 的 Object.defineProperty() 来重新定义这个属性,此外,还可以使用 hasOwnProperty() 方法来过滤掉。

    2. for 和 for in 遍历数组时下标类型不一样。

    let colors = ['red', 'green', 'yellow'];
    for (let i in colors) {
      console.log(typeof i);  // string string string
    }
    for (let i = 0; i < colors.length; i ++) {
      console.log(typeof i);  // number number number
    }
    

    3. 对于不存在的数组项的处理差异。
    对于数组来讲,我们知道如果将其 length 属性设置为大于数组项数的值,则新增的每一项都会得到 undefined 的值。

    let colors = ['red', 'green', 'yellow'];
    // 将数组长度变为 10
    colors.length = 10;
    // 在添加一个元素到数组末尾
    colors.push('blue');
    for (let i in colors) {
      console.log(i);  // 0 1 2 10
    }
    

    Object.keys()

    Object.keys() 返回对象自身的所有可枚举的属性的键名。返回一个由属性名组成的数组。

    // 遍历数组
    let colors = ['red', 'green', 'yellow'];
    colors.length = 10;
    colors.push('blue');
    Array.prototype.demo = function () {};
    console.log(Object.keys(colors));  // ["0", "1", "2", "10"]
    
    // 遍历对象
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    Person.prototype.demo = function() {};
    var jenemy = new Person('jenemy', 25);
    console.log(Object.keys(jenemy));  // ["name", "age"]
    

    Object.getOwnPropertyNames()

    Object.getOwnPropertyNames() 方法返回对象的所有自身属性的属性名(包括不可枚举的属性)组成的数组,但不会获取原型链上的属性。

    A.prototype.date = Date();
    function A (a, b) {
      this.a = a;
      this.b = b;
      this.getA = function () {
        return this.a;
      }
    }
    let a = new A('b', 'bb');
    a.getB = function () {};
    Object.defineProperty(a, 'demo', {
      value: function () {  }
    })
    console.log(Object.getOwnPropertyNames(a));  // ["a", "b", "getA", "getB", "demo"]
    

    总结:其实这几个方法之间的差异主要在属性是否可可枚举,是来自原型,还是实例。

    方法 适用范围 描述
    for..in 数组,对象 获取可枚举的实例和原型属性名
    Object.keys() 数组,对象 返回可枚举的实例属性名组成的数组
    Object.getPropertyNames() 数组,对象 返回除原型属性以外的所有属性(包括不可枚举的属性)名组成的数组

    相关文章

      网友评论

          本文标题:js 中 for 和 for in 遍历数组区别及Object.

          本文链接:https://www.haomeiwen.com/subject/fuptwctx.html