• (66)Wangdao.com第十一天_JavaScript 数组Array


    数组 Array

    本质上,数组属于一种特殊的对象。typeof 运算符会返回数组的类型是 object

    • 数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2...)
      // Object.keys方法返回数组的所有键名。
      
      var arr = ['a', 'b', 'c'];
      Object.keys(arr);    // ["0", "1", "2"]    // 可以看到数组的键名就是整数0、1、2。
    • 数组的键名其实也是字符串。之所以可以用数值读取,是因为非字符串的键名会被转为字符串
    • JavaScript 使用一个32位整数,保存数组的元素个数。这意味着,数组成员最多只有 4294967295 个(232 - 1)个,也就是说length属性的最大值就是 4294967295

    与普通对象的区别是 "数组使用数字作为索引 [index] 来操作属性"。index 从 0 开始。

    数组的存储性能相对较好。

    var arr = ['唐僧','孙悟空','猪八戒','沙和尚','白龙马'];


     

    1. 创建数组对象

    • var arr = new Array();    // typeof arr    返回 object

    2. 给数组添加对象

    • arr[0] = 1;     // console.log(arr)    打印 "1"
      arr[1] = 11;    // console.log(arr)    打印 "1,11"
      arr[2] = 22;    // console.log(arr)    打印 "1,11,22"

    3. 读取数组对象

    • console.log(arr[0]);    // 1
      console.log(arr[1]);    // 11
      console.log(arr[2]);    // 22
      console.log(arr[3]);    // undefined    不会报错

    4. 获取数组长度

    • arr.length 总是返回  "最大索引值+1" ,所以尽量避免创建不连续数组
      var arr = [1,2,3];
      console.log(arr.length);    // 返回 3 ,因为有 3 个元素 arr[0],arr[1],arr[2]
      
      arr.[100] = 100;     // 此时数组有4个元素 arr[0],arr[1],arr[2],arr[100]
      console.log(arr.length);    // 但是会返回 101 , 实际只有 4 个元素, 这四个元素以外的其他 97 个元素值都为 undefined, 且用 in 判断时返回 false
    • 清空数组的一个有效方法,就是将 arr.length属性设为 0
      var arr = [ 'a', 'b', 'c' ];
      
      arr.length = 0;
      arr    // []
    • b
    • b
    •  

    5. 在数组最后添加元素

    • // 根据上一个特性,可以在数组最后追加一个元素
      arr[arr.length] = 666;

     

    1. 使用字面量来创建数组

    • var arr = [];    // 和 new Array() 效果相同

    2. 在创建时指定元素

    • var arr = [0,1,2,3,4];
      
      // 等同于
      var arr = new Array(0,1,2,3,4);

    3. 创建一个只有一个元素的数组

    • var arr = [10];    // 此时数组只有1个元素,arr[0] = 10;
      
      
      var arr = new Array(10);    // 此时创建了一个长度为10的数组!!!
      // 每个元素的值都为 undefined

    4. 数组中元素可以放任意数据类型的数据

    • var arr = ["Hello","How",1,2,3,null,undefined,true,false];
      
      // 数组元素是对象
      var sun = {name:"孙悟空"};
      arr[arr.length] = sun;
      console.log(arr[arr.length-1].name);    // 将会打印 "孙悟空"
      
      
      // 数组元素是函数
      var arr = [
          function(){console.log("Hello!"},
          function(){console.log("Hi!")}
      ];
      
      // 数组 里面放 数组
      var newArr = [["01","02","03"],[0,1,2],["11","22","33"]];
      
      // 混合着放
      var arr = [
        {a: 1},    // 对象
        [1, 2, 3],    // 数组
        function() {return true;}    // 函数
      ];
      
      arr[0]    // Object {a: 1}
      arr[1]    // [1, 2, 3]
      arr[2]    // function (){return true;}

    5. 遍历数组

    • for...in 循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象
      var a = [1, 2, 3];
      
      for (var i in a) {
          console.log(a[i]);    // 1 2 3
      }
    • 但是,for...in不仅会遍历数组所有的数字键,还会遍历非数字键。所以,不推荐使用 for...in 遍历数组。
      var a = [1, 2, 3];
      a.foo = true;
      
      for (var key in a) {
          console.log(key);    // 0 1 2 foo
          console.log(key);    // 1 2 3 true
      }
    • 数组的遍历可以考虑使用 for循环 while循环
      var a = [1, 2, 3];
      
      // for循环
      for(var i = 0; i < a.length; i++) {
          console.log(a[i]);
      }
      
      // while循环
      var i = 0;
      while (i < a.length) {
          console.log(a[i]);
          i++;
      }
      
      // 逆向遍历
      var l = a.length;
      while (l--) {
          console.log(a[l]);
      }
    • 数组的 arr.forEach() 方法,也可以用来遍历数组
      var colors = ['red', 'green', 'blue'];
      colors.forEach(function (color) {
          console.log(color);    // red green blue
      });
    • 数组的空位 hole        不影响length属性
      • 当数组的某个位置是空元素,即两个逗号之间没有任何值,我们称该数组存在空位(hole)
      • 如果最后一个元素后面有逗号,并不会产生空位。也就是说,有没有这个逗号,结果都是一样的。
        var a = ['a' , , 'c'];
        a.length     // 3
        // 数组的空位是可以读取的,返回undefined
        a[0] // 'a'
        a[1] // undefined
        a[2] // 'c'

        var a = [1, 2, 3,];
        a.length // 3
    • delete 命令删除一个数组成员,会形成空位,并且不会影响length属性
      var a = [1, 2, 3];
      delete a[1];
      
      a[1]    // undefined
      a.length    // 3
    • 数组的某个位置是空位,与某个位置是undefined,是不一样的。
      • 如果是空位,使用数组的forEach方法、for...in结构、以及Object.keys方法进行遍历,空位都会被跳过
        var a = [, , ,];
        
        a.forEach(function (x, i) {
            console.log(i + '. ' + x);    // 不产生任何输出
        })
        
        for (var i in a) {
            console.log(i);    // 不产生任何输出
        }
        
        Object.keys(a)    // []
      • 如果某个位置是 undefined,遍历的时候就不会被跳过
        var a = [undefined, undefined, undefined];
        
        a.forEach(function (x, i) {
            console.log(i + '. ' + x);
        });
        // 0. undefined
        // 1. undefined
        // 2. undefined
        
        for (var i in a) {
            console.log(i);    // 0 1 2
        }
        
        Object.keys(a)    // ['0', '1', '2']

    6. 类似数组对象

    • 如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,语法上称为“类似数组的对象”(array-like object)。
      var obj = {
        0: 'a',
        1: 'b',
        2: 'c',
        length: 3
      };
      
      obj[0] // 'a'
      obj[1] // 'b'
      obj.length // 3
      obj.push('d')    // TypeError: obj.push is not a function
      // 因为它们不具备数组特有的方法。
      // 对象obj没有数组的push方法,使用该方法就会报错。
    • 有一个问题,这种length属性不是动态值,不会随着成员的变化而变化
    • 典型的“类似数组的对象”有 函数的arguments对象,以及大多数 DOM 元素集,还有字符串
    • 数组的slice方法可以将 “类似数组的对象” 变成真正的数组
      • var arr = Array.prototype.slice.call(arrayLike);
    • 通过call(),可以把 forEach() 嫁接到 arrayLike 上面调用
      • 如:在arguments对象上面调用forEach方法。
        // forEach 方法
        function logArgs() {
            Array.prototype.forEach.call(arguments, function (elem, i) {
                console.log(i + '. ' + elem);
            });
        }
        
        // 等同于 for 循环
        function logArgs() {
            for (var i = 0; i < arguments.length; i++) {
                console.log(i + '. ' + arguments[i]);
            }
        }
    • 注意,这种方法比直接使用数组原生的forEach要慢,
    • 所以最好还是先将“类似数组的对象”转为真正的数组,然后再直接调用数组的forEach方法。
      var arr = Array.prototype.slice.call('abc');
      arr.forEach(function (chr) {
            console.log(chr);    // a b c
      });

    7. 数组的静态方法

    • Array.isArray()    判断变量是否是数组
      var arr = [1, 2, 3];
      
      typeof arr // "object"
      Array.isArray(arr) // true

    8. 数组的实例方法

    • .valueOf()    数组的 valueOf方法 返回数组本身。。。不同对象的valueOf方法不尽一致
    • .toString()    数组的toString方法 返回数组的字符串形式
    • .push()    用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
      • var arr = [];
        
        arr.push(1);    // 1
        arr.push('a');    // 2
        arr.push(true, {});    // 4
        
        // arr = [1, 'a', true, {}]
    • .pop()    用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组
      • var arr = ['a', 'b', 'c'];
        
        arr.pop()    // 'c'
        
        // arr = ['a', 'b']

        对空数组使用pop方法,不会报错,而是返回undefined

      • pushpop结合使用,就构成了“后进先出”的栈结构(stack)
    • .shift()    用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组
      • shift方法可以遍历并清空一个数组。
        var list = [1, 2, 3, 4, 5, 6];
        var item;
        
        while (item = list.shift()) {
            console.log(item);
        }
        
        list     // []
      • pushshift结合使用,就构成了“先进先出”的队列结构(queue)
    • .unshift()    用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
      • unshift方法可以接受多个参数,这些参数都会添加到目标数组头部

     

    • .join()    以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。
      • var a = [1, 2, 3, 4];
        
        a.join(' ');    // '1 2 3 4'
        a.join(' | ');    // "1 | 2 | 3 | 4"
        a.join();    // "1,2,3,4"
        [undefined, null].join('#')    // '#'
        
        ['a',, 'b'].join('-')    // 'a--b'

        如果数组成员是undefinednull或空位,会被转成空字符串

      • 通过call方法,这个方法也可以用于字符串或类似数组的对象
        Array.prototype.join.call('hello', '-')    // "h-e-l-l-o"
        
        var obj = { 0: 'a', 1: 'b', length: 2 };
        Array.prototype.join.call(obj, '-')    // 'a-b'
    • .concat()    用于多个数组的合并。
      • 它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变
      • ['hello'].concat(['world']);    // ["hello", "world"]
        
        ['hello'].concat(['world'], ['!']);    // ["hello", "world", "!"]
        
        [].concat({a: 1}, {b: 2});    // [{ a: 1 }, { b: 2 }]
        
        [2].concat({a: 1});    // [2, {a: 1}]
      • 如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用
        • 改变原对象以后,新数组跟着改变

     

    • .reverse()    颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组

     

    • .slice(start, end)    用于提取目标数组的一部分,返回一个新数组,原数组不变
      • 它的第一个参数为起始位置(从0开始),
      • 第二个参数为终止位置(但该位置的元素本身不包括在内)。如果省略第二个参数,则一直返回到原数组的最后一个成员
      • 如果slice方法的参数是负数,则表示倒数计算的位置
      • 如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。
      • var a = ['a', 'b', 'c'];
        a.slice(-2);    // ["b", "c"]
        a.slice(-2, -1);    // ["b"]
        
        var a = ['a', 'b', 'c'];
        a.slice(4);    // []
        a.slice(2, 1);    // []
      • Array.prototype.slice().call()方法的一个重要应用,是 将类似数组的对象转为真正的数组
        Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })    // ['a', 'b']
        
        Array.prototype.slice.call(document.querySelectorAll("div"));
        Array.prototype.slice.call(arguments);
    • .splice(start, count, addElement1, addElement2, ...)    
      • 用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组
      • 第一个参数是删除的起始位置(从0开始),起始位置如果是负数,就表示从倒数位置开始删除。
      • 第二个参数是被删除的元素个数,
      • 如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。
      • 如果只提供第一个参数,从起始位置开始,删除后面所有元素组成一个数组返回

     

    • .sort()    对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变
      • 数值会被先转成字符串,再按照字典顺序进行比较所以101排在11的前面
      • 如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数
        • 函数本身接受两个参数,表示进行比较的两个数组成员。如果该函数的返回值大于0,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面。
          [10111, 1101, 111].sort(function (a, b) {
              return a - b;
          });    // [111, 1101, 10111]
          [
              { name: "张三", age: 30 },
              { name: "李四", age: 24 },
              { name: "王五", age: 28  }
          ].sort(function (o1, o2) {
              return o1.age - o2.age;
          });
          
          // [
          //     { name: "李四", age: 24 },
          //     { name: "王五", age: 28  },
          //     { name: "张三", age: 30 }
          // ]
    • .map()    方法
      • 将数组的所有成员依次传入参数函数,
      • 然后把每一次的执行结果组成一个新数组返回。。。原数组没有变化
        • var numbers = [1, 2, 3];
          
          numbers.map(function (n) {
              return n + 1;
          });    // [2, 3, 4]
          
          numbers    // [1, 2, 3]
      • 该函数调用时,map方法向它传入三个参数:当前成员 elem、当前位置 index数组本身 arr
        • [1, 2, 3].map(function(elem, index, arr) {
            return elem * index;
          });    // [0, 2, 6]
      • map方法还可以接受第二个参数,用来绑定回调函数内部的this变量
        • var arr = ['a', 'b', 'c'];
          
          [1, 2].map(function (e) {
              return this[e];
          }, arr)    // ['b', 'c']
      • 如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位 (不会跳过不会跳过undefinednull)
        • var f = function (n) { return 'a' };
          
          [1, undefined, 2].map(f);    // ["a", "a", "a"]
          [1, null, 2].map(f);    // ["a", "a", "a"]
          [1, , 2].map(f);    // ["a", , "a"]
    • .forEach()    
      • map方法很相似,也是对数组的所有成员依次执行参数函数
      • 但是,forEach方法不返回值,只用来操作数据。
      • 这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法
      • 参数是一个函数,该函数同样接受三个参数:当前成员 elem、当前位置 index数组本身 arr
      • forEach方法也可以接受第二个参数,绑定参数函数的 this 变量
      • forEach方法也会跳过数组的空位 , 不会跳过undefinednull
      • var out = [];
        
        [1, 2, 3].forEach(function(elem) {
           this.push(elem * elem);
        }, out);
        
        out    // [1, 4, 9]
      • 注意 : 
        • forEach方法无法中断执行,总是会将所有成员遍历完。
        • 如果希望符合某种条件时,就中断遍历,要使用for循环
    • .filter()    用于过滤数组成员,满足条件的成员组成一个新数组返回
      • 参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
        • [1, 2, 3, 4, 5].filter(function (elem) {
              return (elem > 3);
          });    // [4, 5]    将大于3的数组成员,作为一个新数组返回
          
          
          var arr = [0, 1, 'a', false];
          
          arr.filter(Boolean);    // [1, "a"]    获取所有布尔值为true的成员
      • 函数可以接受三个参数:当前成员 elem、当前位置 index数组本身 arr
        • [1, 2, 3, 4, 5].filter(function (elem, index, arr) {
              return index % 2 === 0;
          });    // [1, 3, 5]
      • filter方法还可以接受第二个参数,用来绑定参数函数内部的this变量
        • var obj = { MAX: 3 };
          var myFilter = function (item) {
              if (item > this.MAX) return true;
          };
          
          var arr = [2, 8, 3, 4, 1, 3, 2, 9];
          arr.filter(myFilter, obj);    // [8, 4, 9]
    • .some() 和 every()
        • 这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合某种条件
        • 接受一个函数作为参数,所有数组成员依次执行该函数。然后返回一个布尔值
        • 该函数接受三个参数:当前成员 elem、当前位置 index数组本身 arr
      • some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false
        • var arr = [1, 2, 3, 4, 5];
          arr.some(function (elem, index, arr) {
              return elem >= 3;
          });    // true
      • every方法是所有成员的返回值都是true,整个every方法才返回true,否则返回false
        • var arr = [1, 2, 3, 4, 5];
          arr.every(function (elem, index, arr) {
              return elem >= 3;
          });    // false
      • 注意,对于空数组,some方法返回falseevery方法返回true,回调函数都不会执行

     

    • .reduce()  和  .reduceRight()  
      • 依次处理数组的每个成员,最终累计为一个值。
      • 它们的差别是 : 
        • reduce是从左到右处理(从第一个成员到最后一个成员)
        • reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样
      • // 求出数组所有成员的和
        [1, 2, 3, 4, 5].reduce(function (a, b) { console.log(a, b); return a + b; }); // 1 2 第一次执行, a是数组的第一个成员1b是数组的第二个成员2 // 3 3 第二次执行, a为上一轮的返回值3b为第三个成员3 // 6 4 第三次执行, a为上一轮的返回值6b为第四个成员4 // 10 5 第四次执行, a为上一轮返回值10b为第五个成员5 // 最后结果:15
      • reduce() 和 reduceRight() 的第一个参数都是一个函数。该函数接受以下四个参数
        • 累积变量,默认为数组的第一个成员
        • 当前变量,默认为数组的第二个成员
        • 当前位置(默认从0开始)
        • 原数组
        • 只有前两个是必须的,后两个则是可选的
      • 如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数
        • [1, 2, 3, 4, 5].reduce(function (a, b) {
              return a + b;
          }, 10);    // 25
          // 指定参数a的初值为10,所以数组从10开始累加,最终结果为25。
          // 注意,这时b是从数组的第一个成员开始遍历
      • 由于空数组取不到初始值,reduce方法会报错。这时,加上第二个参数,就能保证总是会返回一个值
      • function substract(prev, cur) {
            return prev - cur;
        }
        // 比较    reduce()    reduceRight()
        [3, 2, 1].reduce(substract) // 0
        [3, 2, 1].reduceRight(substract) // -4
      • 还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员
        • function findLongest(entries) {
              return entries.reduce(function (longest, entry) {
                  return entry.length > longest.length ? entry : longest;
              }, '');
          }
          
          findLongest(['aaa', 'bb', 'c']);     // "aaa"
    • .indexOf()    返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
      • 还可以接受第二个参数,表示搜索的开始位置
        var a = ['a', 'b', 'c'];
        
        a.indexOf('b');    // 1
        a.indexOf('y');    // -1
        
        ['a', 'b', 'c'].indexOf('a', 1);    // -1    结果为-1,表示没有搜索到
    • .lastIndexOf()    返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1
      • var a = [2, 5, 9, 2];
        a.lastIndexOf(2);    // 3

        a.lastIndexOf(7); // -1
        [NaN].indexOf(NaN) // -1
        [NaN].lastIndexOf(NaN) // -1
      • 不能用来搜索NaN的位置,即它们无法确定数组成员是否包含NaN

     

    • 有不少返回的还是数组,所以可以链式使用
      • var users = [
            {name: 'tom', email: 'tom@example.com'},
            {name: 'peter', email: 'peter@example.com'}
        ];
        
        users
        .map(function (user) {
            return user.email;
        })
        .filter(function (email) {
            return /^t/.test(email);
        })
        .forEach(function (email) {
            console.log(email);
        });
        // 先产生一个所有 Email 地址组成的数组,然后再过滤出以t开头的 Email 地址,最后将它打印出来
    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    poj1141
    poj1260
    poj1080
    poj1221
    用Microsoft Office SharePoint Designer 2007开发aspx
    在Web Part中使用User Control
    MOSS中的WebPart开发
    在MOSS中开发一个模块化的feature
    SharePoint Web Service的身份验证
    MOSS中对列表的一些操作(创建,查询等)
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/9708906.html
Copyright © 2020-2023  润新知