Javascript常用的数组方法

Javascript有很多数组的方法,有的人有W3C的API,还可以去MDN上去找,但是我觉得API上说的不全,MDN上又太多。。其实常用的就那几个,很多都可以用那几个方法解出来。

很多方法中有兼容性的,在使用的时候,把兼容代码复制粘贴即可。

先贴上来数组和字符串的方法的比较,我在学习的时候也是会混。所以做了小总结。之后就是数组方法和一些实例。如果有侧边栏就好了,看得就比较清楚。

数组 字符串

slice | slice substring 截取需要开始和结束index的

splice | substr 截取需要开始index和截取长度的

concat | concat 都是连接,一个是连接数组,一个是连接字符串

indexOf | indexOf 搜索元素在不在里面,返回index值或者-1

join | split 这就是两个反义词啊,相互转化的利器

  • 截取方法中,字符串有三种方法slice / substring / substr ,数组方法有两个slice / splice
    其中字符串的slice 和 substring 是要开始和结束的索引,substr 是要开始索引和长度
    数组的slice是要开始和结束索引,但是splice是要开始索引和长度
  • 搜索元素方法中,数组和字符串都有indexOf方法,但是字符串多出来两种方法charAt和charCodeAt
    其中indexOf是返回索引,charAt是返回索引对应的值,charCodeAt是返回对应值的ASCII码值。
  • 数组的遍历有4中方法,map,every,foreach,some,filter
    其中foreach开始就停不下来,全部遍历。every遍历一个就判断一下,true就继续遍历下一个,false就跳出。map就是边遍历边运算。some返回的是布尔值,符合就是true,不符合就是false。filter返回的是符合元素组成的数组。
  • 增加数组元素,前面unshift,后面push
    移除数组元素,前面shift,后面pop
  • 数组和字符串都有concat方法,各自连接各自的,是数组就连接到数组,字符串就连接成字符串
  • 比较重要的两个就是数组和字符串之间的转化的两个方法
    join是数组转字符串,split是字符串转数组

数组

Array.prototype

Array.prototype 属性表示构造函数的原型,并允许您向所有Array对象添加新的属性和方法。

/*
如果JavaScript本身不提供 first() 方法,
添加一个返回数组的第一个元素的新方法。
*/ 

if(!Array.prototype.first) {
    Array.prototype.first = function() {
        return this[0];
    }
}

Array.prototype本身也是一个 Array

Array.isArray(Array.prototype); 
// true

//属性
Array.prototype.constructor
//所有的数组实例都继承了这个属性,它的值就是 Array,表明了所有的数组都是由 Array 构造出来的。
Array.prototype.length
//上面说了,因为 Array.prototype 也是个数组,所以它也有 length 属性,这个值为 0,因为它是个空数组。

判断是不是数组的方式

Array.isArray( );

Array.isArray( obj );

  • 静态方法,是数组构造函数的方法

  • obj是需要检测的值,如果是数组,返回true,否则返回false

    // 下面的函数调用都返回 true
    Array.isArray([]);
    Array.isArray([1]);
    Array.isArray(new Array());
    // 鲜为人知的事实:其实 Array.prototype 也是一个数组。
    Array.isArray(Array.prototype); 
    
    // 下面的函数调用都返回 false
    Array.isArray();
    Array.isArray({});
    Array.isArray(null);
    Array.isArray(undefined);
    Array.isArray(17);
    Array.isArray('Array');
    Array.isArray(true);
    Array.isArray(false);
    Array.isArray({ __proto__: Array.prototype });
    
  • 存在兼容问题(IE8及以下不支持)

    //Polyfill
    //假如不存在 Array.isArray(),则在其他代码之前运行下面的代码将创建该方法。
    if (!Array.isArray) {
      Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
      };
    }
    

(Object.prototype)toString.call(arr) -> [object Array]

Object.prototype.toString.call([]) -> [ object Array]

  • 转化成字符串是"[object Array]",可以作为判断条件。
  • Object.prototype.toString.call(obj).slice(8,-1); -> ==='Array'
  • ({}).toString.call(function(){}).slice(8,-1); -> ==='Function'
  • slice截取,前面的是从第八个开始,截取到倒数的第二个。

instanceof

对象 instanceof 数据类型

  • console.log(obj instanceof Array);

  • (不严谨)多个页面进行判断,会有问题

    //iframe
      /*B页面嵌套到A页面中,每个页面都有一个top属性,top属性一直都指向A页面的window,所以在A页面定义的函数fn,暴露在B页面的全局环境中,在B页面中也可以调用。*/
      top.fn(); //(就是调用页面A的fn函数)
    
    //那么问题来了:
    B页面:  top.fn([]);
    A页面:  function fn(arr){
              console.log(arr instanceof Array);
              }  //此时会成为false
    
    //要直接访问A页面,访问B页面会报错,因为只打开的页面的top指向自己的window,此时调用了没有定义的函数。
    //防止被嵌套:if( top != window){
          top.location.href = ‘inner-B.html’;} //跳转到自己的地址
    

数组长度

  • 数组的length属性总是比数组中定义的最后一个元素的下标大一,表示数组中元素的个数。

  • 数组的length属性在创建数组的时候初始化,在添加新元素的时候数组长度改变

    //如果函数中没有参数,a为空数组
    var a = new Array();   // a.length 被初始化为 0
    
    //如果函数参数是一个,参数表示函数的长度
    var b = new Array(10); // b.length 被初始化为 10
    
    //如果函数参数是两个及以上,参数表示数组内容
    var c = new Array("one", "two", "three");  // c.length 被初始化为 3
    c[3] = "four";        // c.length 被更新为 4
    c[10] = "blastoff";   // c.length 变为 11 
    
  • 设置属性length的值可以改变数组的大小,设置值小则被从后截断,设置值大则剩下的值都为undefined

    var a = new Array("one", "two", "three");
    a.length = 2;  //["one", "two"]
    a.length = 5;  //["one", "two", undefined × 3]
    

遍历数组

map

var new_array = array.map (function(value,index,array){ },thisArg);

  • 遍历数组,能够将数组转化为一个新的数组,新数组的值由map方法回调函数的返回值决定。

  • 回调函数的第一个参数是数组的值,第二个参数是索引,第三个参数是被调用的数组。thisArg可选,执行 callback函数时 使用的this值。

  • 如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this都会指向thisArg参数上的这个对象。如果省略了 thisArg参数,或者赋值为null或undefined,则 this 指向全局对象 。

  • 返回值是新的数组

 var arrNew = arr.map(function(value,index){
     console.log(‘索引是’+index+”,内容是:”+value+);
   })
      
 let numbers = [1, 5, 10, 15];
 let roots = numbers.map(function(x) {
      return x * 2;
   });
// roots is now [2, 10, 20, 30]
// numbers is still [1, 5, 10, 15]
  • 求数组中每个元素的平方根

    var numbers = [1, 4, 9];
    var roots = numbers.map(Math.sqrt);
    /* roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9] */
    
  • 使用 map 重新格式化数组中的对象

    var kvArray = [{key:1, value:10}, 
                   {key:2, value:20}, 
                   {key:3, value: 30}];
    var reformattedArray = kvArray.map(function(obj){ 
      //obj指的是每一个数组元素,是一个对象
       var rObj = {};
       rObj[obj.key] = obj.value;
       return rObj;
    });
    // reformattedArray is now [{1:10}, {2:20}, {3:30}], 
    // kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
    
  • 将数组中的单词转换成对应的复数形式

    var words = ["foot", "goose", "moose", "kangaroo"];
    //定义函数
    function fuzzyPlural(single) {
      //所有的o变成e
      var result = single.replace(/o/g, 'e');  
      if( single === 'kangaroo'){
        result += 'se';
      }
      return result; 
    }
    //遍历每一个元素
    console.log(words.map(fuzzyPlural));
    // ["feet", "geese", "meese", "kangareese"]
    
  • 如何让一个string使用map方法获取字符串中每个字符所对应的ASCII码组成的数组

    var map = Array.prototype.map
    var a = map.call("Hello World", function(x) { 
      return x.charCodeAt(0); 
    })
    // a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
    
  • 如何遍历querySelectorAll得到动态对象集合

    var elems = document.querySelectorAll('select option:checked');
    var values = Array.prototype.map.call(elems, function(obj) {
      return obj.value;
    });
    
  • 反转字符串

    var str = '12345';
    Array.prototype.map.call(str, function(x) {
      return x;
    }).reverse().join(''); 
    
    // Output: '54321'
    
  • parseInt等有多个参数的函数要注意

    var a = ['1','2','3'];
    var b = a.map(function(x){
      return parseInt(x);
     }); //[1,2,3]
    
     // 下面的语句返回什么呢:
      ["1", "2", "3"].map(parseInt);
      // 你可能觉的会是[1, 2, 3]
      // 但实际的结果是 [1, NaN, NaN]
    
      //parseInt有两个参数,第二个数是进制数
      //所以以上函数主要执行的是
      var a  = ['1','2','3'];
      var b = a.map(function(ele,index,array){
        return parseInt(ele,index);
        //第三个参数parseInt会忽视, 但第二个参数不会
        // parseInt把传过来的索引值当成进制数来使用
        //而第二个参数假如经过 Number 函数转换后为 0 或 NaN,则将会忽略
        //parseInt(1,0);       1
        //parseInt(2,1);       NaN
        //parseInt(3,2);       NaN
      })
    
      //解决如下
      function returnInt(element){
        return parseInt(element,10);
      }
      ["1", "2", "3"].map(returnInt);
      // 返回[1,2,3]
    
  • 兼容问题 IE8及以下不支持

    // 实现 ECMA-262, Edition 5, 15.4.4.19
    // 参考: http://es5.github.com/#x15.4.4.19
    // 兼容代码
    if (!Array.prototype.map) {
      Array.prototype.map = function(callback, thisArg) {
    
        var T, A, k;
        if (this == null) {
          throw new TypeError(" this is null or not defined");
        }
        // 1. 将O赋值为调用map方法的数组.
        var O = Object(this);
        // 2.将len赋值为数组O的长度.
        var len = O.length >>> 0;
        // 3.如果callback不是函数,则抛出TypeError异常.
        if (Object.prototype.toString.call(callback) != "[object Function]") {
          throw new TypeError(callback + " is not a function");
        }
        // 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
        if (thisArg) {
          T = thisArg;
        }
        // 5. 创建新数组A,长度为原数组O长度len
        A = new Array(len);
        // 6. 将k赋值为0
        k = 0;
        // 7. 当 k < len 时,执行循环.
        while(k < len) {
          var kValue, mappedValue;
          //遍历O,k为原数组索引
          if (k in O) {
            //kValue为索引k对应的值.
            kValue = O[ k ];
            // 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
            mappedValue = callback.call(T, kValue, k, O);
            // 返回值添加到新数组A中.
            A[ k ] = mappedValue;
          }
          // k自增1
          k++;
        }
        // 8. 返回新数组A
        return A;
      };      
    }
    

forEach

array.forEach(function(value,index,array){},thisArg);

  • 遍历数组,跑起来就停不下来,调用就会遍历整个数组,无法中断循环

  • 回调函数的第一个参数表示数组中的每一个元素,第二个表示索引号,第三个表示正在操作的数组,可选

  • 返回值undefined

    //实例
    function logArrayElements(element, index, array) {
        console.log("a[" + index + "] = " + element);
    }
    
    // 注意索引2被跳过了,因为在数组的这个位置没有项
    [2, 5, ,9].forEach(logArrayElements);
    // a[0] = 2
    // a[1] = 5
    // a[3] = 9
    
    [2, 5,"" ,9].forEach(logArrayElements);
    // a[0] = 2
    // a[1] = 5
    // a[2] = 
    // a[3] = 9
    
  • 使用thisArg

    因为thisArg参数(this)传给了forEach(),每次调用时,它都被传给callback函数,作为它的this值。但是在ES6的箭头函数表达式传入函数参数,thisArg参数会被忽略,因为箭头函数在词法上绑定了this值。

    function Counter() {
        this.sum = 0;
        this.count = 0;
    }
    
    Counter.prototype.add = function(array) {
        array.forEach(function(entry) {
            this.sum += entry;
            ++this.count;
        }, this);
        //console.log(this);
    };
    
    var obj = new Counter();
    obj.add([1, 3, 5, 7]);
    obj.count; 
    // 4 === (1+1+1+1)
    obj.sum;
    // 16 === (1+3+5+7)
    
  • 兼容问题 IE8及以下不支持

    // Production steps of ECMA-262, Edition 5, 15.4.4.18
    // Reference: http://es5.github.io/#x15.4.4.18
    if (!Array.prototype.forEach){
      Array.prototype.forEach = function(callback, thisArg) {
       
        var T, k;
        if (this == null) {
          throw new TypeError(' this is null or not defined');
        }
        // 1. Let O be the result of calling toObject() passing the
        // |this| value as the argument.
        var O = Object(this);
        // 2. Let lenValue be the result of calling the Get() internal
        // method of O with the argument "length".
        // 3. Let len be toUint32(lenValue).
        var len = O.length >>> 0;
        // 4. If isCallable(callback) is false, throw a TypeError exception. 
        // See: http://es5.github.com/#x9.11
        if (typeof callback !== "function") {
          throw new TypeError(callback + ' is not a function');
        }
        // 5. If thisArg was supplied, let T be thisArg; else let
        // T be undefined.
        if (arguments.length > 1) {
          T = thisArg;
        }
        // 6. Let k be 0
        k = 0;
        // 7. Repeat, while k < len
        while (k < len) {
          var kValue;
          // a. Let Pk be ToString(k).
          //    This is implicit for LHS operands of the in operator
          // b. Let kPresent be the result of calling the HasProperty
          //    internal method of O with argument Pk.
          //    This step can be combined with c
          // c. If kPresent is true, then
          if (k in O) {
            // i. Let kValue be the result of calling the Get internal
            // method of O with argument Pk.
            kValue = O[k];
            // ii. Call the Call internal method of callback with T as
            // the this value and argument list containing kValue, k, and O.
            callback.call(T, kValue, k, O);
          }
          // d. Increase k by 1.
          k++;
        }
        // 8. return undefined
      };
    }
    

every

array.every(function(value,index){});

  • 根据当前回调函数的返回值决定是否进行下一次循环

    • 如果没有return true,则只是执行一次
    • 回调函数的返回值为true,继续循环
    • 返回值是false,停止循环
  • 第一个参数是数组中的每一个元素 第二个参数表示索引号

  • 兼容问题 IE8及以下不支持

    //兼容问题
    if (!Array.prototype.every){
      Array.prototype.every = function(fun /*, thisArg */){
        'use strict';
    
        if (this === void 0 || this === null)
          throw new TypeError();
    
        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== 'function')
            throw new TypeError();
    
        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; i++){
          if (i in t && !fun.call(thisArg, t[i], i, t))
            return false;
        }
        return true;
      };
    }
    

some(返回布尔)

array.some(callback[,thisArg])

  • callback 被调用时传入三个参数:元素的值,元素的索引,被遍历的数组

  • thisArg参数,将会把它传给被调用的callback,作为this 值。否则,在非严格模式下将会是全局对象,严格模式下是undefined

  • 数组中如果有一个满足条件,返回true,否则返回false

    //callback
    function isBigEnough(element, index, array){
      return (element >= 10);
    }
    var passed = [2, 5, 8, 1, 4].some(isBigEnough);
    // passed is false
    passed = [12, 5, 8, 1, 4].some(isBigEnough);
    // passed is true
    
  • some有兼容问题,IE8及以下不支持

    //兼容代码
    if (!Array.prototype.some){
      Array.prototype.some = function(fun /*, thisArg */){
        'use strict';
        if (this === void 0 || this === null)
           throw new TypeError();
        
        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== 'function')
          throw new TypeError();
    
        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; i++){
          if (i in t && fun.call(thisArg, t[i], i, t))
            return true;
        }
        return false;
      };
    }
    

filter

var new_array = arr.filter(callback[, thisArg])

  • 判断数组中的每一项是否都满足条件,所有满足条件的则返回新数组

  • callback 用来测试数组的每个元素的函数。调用时使用参数 (element, index, array)
    返回true表示保留该元素(通过测试),false则不保留

  • thisArg 可选,执行callback时的用于this的值

  • 这些概念去看some

    function isBigEnough(element) {
      return element >= 10;
    }
    var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
    // filtered is [12, 130, 44]
    
    //另一种写法
    var arr = [12, 5, 8, 130, 44];
    var filt = arr.filter(function(element){
      return element >= 10;
    })//filt is [12, 130, 44]
    
  • filter有兼容问题,IE8及以下不支持

    //兼容代码
    //假定 fn.call 等价于 Function.prototype.call 的初始值,且 Array.prototype.push 拥有它的初始值。
    if (!Array.prototype.filter)
    {
      Array.prototype.filter = function(fun /*, thisArg */)
      {
        "use strict";
    
        if (this === void 0 || this === null)
          throw new TypeError();
    
        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== "function")
          throw new TypeError();
    
        var res = [];
        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; i++)
        {
          if (i in t)
          {
            var val = t[i];
    
            // NOTE: Technically this should Object.defineProperty at
            //       the next index, as push can be affected by
            //       properties on Object.prototype and Array.prototype.
            //       But that method's new, and collisions should be
            //       rare, so use the more-compatible alternative.
            if (fun.call(thisArg, val, i, t))
              res.push(val);
          }
        }
    
        return res;
      };
    }
    

截取数组

slice(索引)

array.slice(start,end)

  • start

    • 正数,数组片段开始截取的下标
    • 负数,从数组尾部开始算起,-1是最后一个,-2是倒数第二个
    • 截取一个生成新数组,不影响原来数组,参数开始从0开始,从-1结束
  • end

    • 结束的后一个元素的数组下标
    • 没有指定参数,则默认是到数组结束
    • 如果是负数,就是从末尾开始算起
  • 截取一个生成新数组,不影响原来数组,包含从start到end(不包括该元素)指定的array元素

    var a = [1,2,3,4,5];
    a.slice(0,3);    // 返回 [1,2,3]
    a.slice(3);      // 返回 [4,5]
    a.slice(1,-1);   // 返回 [2,3,4]
    a.slice(-3,-2);  // 返回 [3]; 
    //IE 4存在的Bug: 返回[1,2,3]
    

splice(长度,可替换)

array.splice(start, deleteCount, value, ...)

  • 参数有start,deleteCount,options(替换)

    • start开始插入和(或)删除的数组元素的下标
    • deleteCount 从start开始(包括start)要删除的元素个数。参数可选,如果没有指定,就默认到结尾的所有元素
    • value,... 要插入的数组值,从start所指的下标处开始插入
  • 返回值是截取到的数组

    //定义一个数组
    var arr = [10,20,30,40,50,60,70,80,90];
    //三个参数的情况  从索引为三的地方数三个,替换这三个数
    var result = arr.splice(3,3,100,200,300);
    //arr = [10,20,30,100,200,300,70,80,90];
    //result = [40,50,60];
    //两个参数的情况  从索引为三的地方截取三个
    var result1 = arr.splice(3,3);
    //arr = [10,20,30,70,80,90];
    //result = [100,200,300];
    //一个参数的情况,是从索引为三的地方一直到最后截取
    var result2 = arr.splice(3);
    //arr = [70,80,90]
    //result2 = [10,20,30]
    

连接数组

join(字符串)

var string = array.join()

  • 如果没有参数,默认用逗号作为分割符

  • 如果有参数,则参数是用于分隔数组元素的字符或字符串

  • 返回字符串,通过把array每个元素转换成字符串,用参数连接起来

  • 可以用String对象的split()方法进行相反的操作,把字符串根据参数分隔成数组

    var a = new Array(1, 2, 3, "testing");
    //a = [1,2,3,testing]
    var s = a.join("+");  // s 是字符串"1+2+3+testing"
    

concat

var new_array = array1.concat('array2','array3')

  • 参数至少是一个

  • 返回一个新数组

  • 如果操作的参数是一个数组,那么添加的是数组中的元素,而不是数组

    var a = [1,2,3];
    a.concat(4, 5)          //返回 [1,2,3,4,5]
    a.concat([4,5]);        //返回 [1,2,3,4,5]
    a.concat([4,5],[6,7])   //返回 [1,2,3,4,5,6,7]
    a.concat(4, [5,[6,7]])  //返回 [1,2,3,4,5,[6,7]]
    

添加元素

push

array.push(value,...)

  • 要添加到array的末尾,可以是一个也可以是多个

  • 返回值是添加后的数组的长度

  • pop()方法和push()方法可以提供先进后出的栈的功能

  • 在对象中添加元素

    var obj = {
        length: 0,
        addElem: function addElem(elem){
            [].push.call(this, elem);
        }
    };
    obj.addElem({});
    obj.addElem({});
    console.log(obj.length);
    // → 2
    

unshift

array.unshift(value, ...)

  • 参数是要添加到头部的一个或多个值
  • 返回数组的新长度

移除元素

pop

array.pop()

  • 删除的是数组中的最后一个元素,数组长度-1
  • 返回值是删除的元素
  • 如果数组为空,则数组长度不变,返回undefined
  • pop()方法和push()方法可以提供先进后出的栈的功能

shift

array.shift()

  • 移除的是数组中的第一个元素,其余的向前移

  • 返回的是移除元素的值

  • 如果是空数组,则不进行任何操作,返回undefined

数组排序

sort

arr.sort(compareFunction)

  • compareFunction 可选。是用来指定按什么顺序进行排序的函数,可选

  • 返回排序后的数组

  • 如果不传参数,将按照字母(字符编码)顺序最数组进行排序,所以要把数组中的元素转化为字符串以便进行比较

  • 如过按照别的顺序进行排序,就要提供比较函数(参数a,b)

    • a < b 排序后a在b之前,就返回一个小于0的值
    • a = b 返回0
    • a > b 排序后a在b之后,返回一个大于0的值
    // 按照数字顺序排序的排序函数
    //a-b 表示升序排列
    function  sortAscending(a, b) { return a - b; }
    //b-a 表示降序排列
    function  sortDescending(a,b) { return b - a; }
    
    var a = new Array(33, 4, 1111, 222);
    // 按照字母顺序的排序
    a.sort();             // 结果为: 1111, 222, 33, 4
    // 按照数字顺序的排序
    a.sort(sortAscending);  //结果为: 4, 33, 222, 1111
    a.sort(sortDescending); //结果为:1111,222,33,4
    

reverse

array.reverse( )

  • 颠倒数组中元素的顺序,不创建新数组

    var a = new Array(1, 2, 3); 
    // a = [1,2,3]    a[0] == 1, a[2] == 3;
    a.reverse(  );             
    //Now  a = [3,2,1]  a[0] == 3, a[2] == 1;
    

查找数组

indexOf(返回索引)

arr.indexOf(searchElement)

arr.indexOf(searchElement[, fromIndex = 0])

  • searchElement 要查找的元素

  • fromIndex 开始查找的位置

    • fromIndex >= length,意味着不会在数组里查找,返回-1
    • 负值,-1从最后一个开始查找,-2从倒数第二个开始找
  • 返回值如果找到了元素就返回元素在数组中的索引位置,若没有找到则返回-1

    var array = [2, 5, 9];
    array.indexOf(2);     // 0
    array.indexOf(7);     // -1
    array.indexOf(9, 2);  // 2
    array.indexOf(2, -1); // -1
    array.indexOf(2, -3); // 0
    
  • 找出指定元素出现的所有位置

    var indices = [];
    var array = ['a', 'b', 'a', 'c', 'a', 'd'];
    var element = 'a';
    //判断元素在不在数组里面
    var idx = array.indexOf(element);
    //如果元素在数组里面,就循环
    while (idx != -1) {
      //把索引推入新数组中
      indices.push(idx);
      //从找到元素的下一个索引开始继续查找
      idx = array.indexOf(element, idx + 1);
    }
    console.log(indices);
    // [0, 2, 4]
    
  • 判断一个元素是否在数组里,不在则更新数组

    //定义一个函数
    function update(vegs, veg) {
      //如果数组中不存在
        if (vegs.indexOf(veg) === -1) {
          //在数组中添加元素
            vegs.push(veg);
          console.log('New vegs is :' + vegs);
          //如果在数组中存在
        } else if (vegs.indexOf(veg) > -1) {
          //这个元素已经存在在数组中
            console.log(veg + ' already exists in the vegs.');
        }
    }
    
    var vegs = ['potato', 'tomato', 'chillies', 'green-pepper'];
     update(vegs, 'spinach'); 
      // New vegs is : potato,tomato,chillies,green-papper,spinach
     update(vegs, 'spinach');
      // spinach already exists in the vegs.
    
    
  • 兼容问题 IE8及以下不兼容

      //兼容代码
      // Production steps of ECMA-262, Edition 5, 15.4.4.14
      // Reference: http://es5.github.io/#x15.4.4.14
      if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function(searchElement, fromIndex) {
    
          var k;
          // 1. Let O be the result of calling ToObject passing
          //    the this value as the argument.
          if (this == null) {
            throw new TypeError('"this" is null or not defined');
          }
          var O = Object(this);
          // 2. Let lenValue be the result of calling the Get
          //    internal method of O with the argument "length".
          // 3. Let len be ToUint32(lenValue).
          var len = O.length >>> 0;
          // 4. If len is 0, return -1.
          if (len === 0) {
            return -1;
          }
          // 5. If argument fromIndex was passed let n be
          //    ToInteger(fromIndex); else let n be 0.
          var n = +fromIndex || 0;
          if (Math.abs(n) === Infinity) {
            n = 0;
          }
          // 6. If n >= len, return -1.
          if (n >= len) {
            return -1;
          }
          // 7. If n >= 0, then Let k be n.
          // 8. Else, n<0, Let k be len - abs(n).
          //    If k is less than 0, then let k be 0.
          k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
          // 9. Repeat, while k < len
          while (k < len) {
            // a. Let Pk be ToString(k).
            //   This is implicit for LHS operands of the in operator
            // b. Let kPresent be the result of calling the
            //    HasProperty internal method of O with argument Pk.
            //   This step can be combined with c
            // c. If kPresent is true, then
            //    i.  Let elementK be the result of calling the Get
            //        internal method of O with the argument ToString(k).
            //   ii.  Let same be the result of applying the
            //        Strict Equality Comparison Algorithm to
            //        searchElement and elementK.
            //  iii.  If same is true, return k.
            if (k in O && O[k] === searchElement) {
              return k;
            }
            k++;
          }
          return -1;
        };
      }
    

©copyright burning.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 本文转载自@陈铮半年前的博文,原文地址:JavaScript Array 原型方法 大盘点 数组是一个超常用的数据...
    浙大javascript联盟阅读 732评论 0 4
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,050评论 1 10
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,716评论 2 17
  • 拓扑排序: 一幅有向图的拓扑排序即为所有顶点的逆后序排列。证明: 对于任意边v->w,在调用dfs(v)时,只会是...
    sleepyjoker阅读 633评论 0 0
  • 作者 费尔南多·佩索阿 你不快乐的每一天都不是你的, 你只是虚度了它。 无论你怎么活 只要不快乐,你就没有生活过。...
    小王子的狐狸先森阅读 240评论 0 0