zoukankan      html  css  js  c++  java
  • JavaScript中对象和数组的遍历方法

    对象的遍历

    对象属性的遍历,方法有以下几种

    • for...in
    • Object.keys()
    • Object.getOwnPropertyNames()

    1. for...in

    for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。

    可枚举属性与不可枚举属性:
    在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的。
    可枚举性决定了这个属性能否被for…in查找遍历到。
    js中基本包装类型的原型属性是不可枚举的,如Object, Array, Number等,
    如果你写出这样的代码遍历其中的属性:
    
    var num = new Number();
    for(var pro in num) {
        console.log("num." + pro + " = " + num[pro]);
    }
    //输出空
    这是因为Number中内置的属性是不可枚举的,所以不能被for…in访问到。
    
    语法
    var obj = {
        name: 'jack',
        age: 33
    }
    for (var n in obj) {
        console.log(n)
    }
    输出:name, age
    

    注意:

    通常为了只枚举对象的私有属性,会用一个判断函数hasOwnProperty()来过滤掉原型中的属性

    Object.prototype.hasOwnProperty方法接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性。

    例1:
    Object.prototype.clone = function() {}
    var obj = {
        name: 'jack',
        age: 33
    }
    for (var n in obj) {
        console.log(n)
    }
    //多出了在原型上定义的方法
    输出:name, age, clone
    
    例2:
    Object.prototype.clone = function () {};
    var obj = {
      name: "jack",
      age: 33,
    };
    for (var n in obj) {
      if (obj.hasOwnProperty(key)) {
        console.log(n);
      }
    }
    
    输出:name, age
    #推荐总是使用 hasOwnProperty 方法,这将会避免原型对象扩展带来的干扰:
    

    2. Object.keys() , Object.getOwnPropertyNames()

    Object.keys方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名。

    一般情况下,几乎总是使用Object.keys方法,遍历对象的属性。

    语法
    var obj = {
      p1: 123,
      p2: 456
    };
    
    Object.keys(obj) // ["p1", "p2"]
    
    var obj = {
      p1: 123,
      p2: 456
    };
    
    Object.getOwnPropertyNames(obj) // ["p1", "p2"]
    

    对于一般的对象来说,Object.keys()Object.getOwnPropertyNames()返回的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果。
    Object.keys方法只返回可枚举的属性(详见《对象属性的描述对象》一章),Object.getOwnPropertyNames方法还返回不可枚举的属性名。

    var a = ['Hello', 'World'];
    
    Object.keys(a) // ["0", "1"]
    Object.getOwnPropertyNames(a) // ["0", "1", "length"]
    //上面代码中,数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。
    

    小结

    • for..in 遍历的是对象的可枚举属性,包括原型
    • Object.keys 遍历的是对象可枚举属性,不包括原型
    • Object.getOwnPropertNames 遍历的是对象的所有属性,不包括原型

    数组项的全部遍历

    全部遍历所列举的方法,是指主要用来枚举数组各项的方法。

    1. for循环

    for循环遍历是最原始,也是性能最高的一种遍历方法。

    var arr = [1,4,7,9]
    for (var i = 0, len = arr.length; i < len; i++) {
        console.log(arr[i]) // 输出 1 4 7 9
    }
    

    2. forEach函数

    forEach()函数是构造函数Array的原型上的函数,即Array.prototype.forEach,因此所有数组都可以用这个方法。
    函数没有返回值,因此主要用来对数组的过程处理。

    forEach方法的回调函数有三个参数,elem为当前成员的值,index为当前成员的位置,arr为原数组([1, 2, 3])。
    var arr = ['a', 'b', 'c']
    arr.forEach((elem, index, arr) => { // 处理函数作为参数
        console.log(index + ' is ' + elem)
    })
    输出
    0 is a
    1 is b
    2 is c
    

    3. map函数

    map()函数也是构造函数Array的原型上的函数,即Array.prototype.mapmap方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

    map方法向它传入三个参数:当前成员、当前位置和数组本身。
    [1, 2, 3].map((elem, index, arr)=> {
      return elem * index;
    });
    // [0, 2, 6]
    

    4. for...of

    for...of是ES6新增的语法,它不仅可以用来遍历数组,还可以遍历字符串,以及ES6中的Map,Set。

    var array = ['a', 'b', 'c']
    for (let item of array) {
        console.log(item) // 输出 a b c
    }
    

    数组项的其他遍历

    1. filter()函数

    filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。

    它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。

    filter方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。
    [1, 2, 3, 4, 5].filter( elem=> {
      return (elem > 3);
    })
    //输出 [4, 5]
    

    2. some(),every()

    这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合某种条件。

    它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。

    some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false

    代码中,如果数组`arr`有一个成员大于等于3,`some`方法就返回`true`
    var arr = [1, 2, 3, 4, 5];
    arr.some( (elem, index, arr)=> {
      return elem >= 3;
    });
    // true
    

    every方法是所有成员的返回值都是true,整个every方法才返回true,否则返回false

    代码中,数组`arr`并非所有成员大于等于`3`,所以返回`false`。
    var arr = [1, 2, 3, 4, 5];
    arr.every(function (elem, index, arr) {
      return elem >= 3;
    });
    // false
    

    注意,对于空数组,some方法返回falseevery方法返回true,回调函数都不会执行。

    3. reduce(),reduceRight()

    reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。

    [1, 2, 3, 4, 5].reduce(function (a, b) {
      console.log(a, b);
      return a + b;
    })
    // 1 2
    // 3 3
    // 6 4
    // 10 5
    //最后结果:15
    

    上面代码中,reduce方法求出数组所有成员的和。整个方法的返回值就是最后一轮的返回值15

    reduce方法和reduceRight方法的第一个参数都是一个函数。该函数接受以下四个参数。

    1. 累积变量,默认为数组的第一个成员
    2. 当前变量,默认为数组的第二个成员
    3. 当前位置(从0开始)
    4. 原数组

    这四个参数之中,只有前两个是必须的,后两个则是可选的。

    如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数。

    [1, 2, 3, 4, 5].reduce(function (a, b) {
      return a + b;
    }, 10);
    // 25
    

    上面代码指定参数a的初值为10,所以数组从10开始累加,最终结果为25。注意,这时b是从数组的第一个成员开始遍历。

    上面的第二个参数相当于设定了默认值,处理空数组时尤其有用。

    function add(prev, cur) {
      return prev + cur;
    }
    
    [].reduce(add)
    //错误:没有初始值的空数组
    // TypeError: Reduce of empty array with no initial value
    
    [].reduce(add, 1)
    // 1
    

    上面代码中,由于空数组取不到初始值,reduce方法会报错。这时,加上第二个参数,就能保证总是会返回一个值。

    由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。

    function findLongest(entries) {
      return entries.reduce(function (longest, entry) {
        return entry.length > longest.length ? entry : longest;
      }, '');
    }
    
    findLongest(['aaa', 'bb', 'c']) // "aaa"
    

    上面代码中,reduce的参数函数会将字符长度较长的那个数组成员,作为累积值。这导致遍历所有成员之后,累积值就是字符长度最长的那个成员。

    4. indexOf(),lastIndexOf()

    indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1

    var a = ['a', 'b', 'c'];
    
    a.indexOf('b') // 1
    a.indexOf('y') // -1
    

    indexOf方法还可以接受第二个参数,表示搜索的开始位置。

    ['a', 'b', 'c'].indexOf('a', 1) // -1
    

    上面代码从1号位置开始搜索字符a,结果为-1,表示没有搜索到。

    lastIndexOf方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1

    var a = [2, 5, 9, 2];
    a.lastIndexOf(2) // 3
    a.lastIndexOf(7) // -1
    

    注意,这两个方法不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN

    [NaN].indexOf(NaN) // -1
    [NaN].lastIndexOf(NaN) // -1
    

    这是因为这两个方法内部,使用严格相等运算符(===)进行比较,而NaN是唯一一个不等于自身的值。

  • 相关阅读:
    jquery easyui 时间控件的使用
    3101 php 学习推荐
    报到
    《C++语言的设计和演化》摘录
    怀念下以前听摇滚乐的日子
    Maven無法下載依賴時的解決方案
    RDF和Jena RDF API入门(2)
    WEB数据挖掘(五)——Aperture数据抽取(1)
    RDF和Jena RDF API入门(1)
    Ubuntu SVN安装配置十分简单
  • 原文地址:https://www.cnblogs.com/cjh1996/p/12699512.html
Copyright © 2011-2022 走看看