• javascript Array对象


    数组是一段线性分配的内存,它通过整数去计算偏移并访问其中的元素。数组是很快的数据结构,但不幸的是,Javascript并没有像这种数组一样的数据结构。Javascript的数组实质是对象,它把数组的下标转换成字符串,用其作为属性,因此它明显比真正的数组慢,但它可以更方便地使用。

    改变自身pop,push,reverse,shift,sort,splice,unshift, 不改变自身concat,join,slice,indexOf,lastIndexOf(后两个为1.6),1.6新增的迭代器:map,filter,forEach,every,some,1.8新增reduce,reduceRight

    Array 对象的方法

    FF: Firefox, N: Netscape, IE: Internet Explorer

    方法 描述 FF N IE
    concat() 方法concat()将创建并返回一个新数组,这个数组是将所有参数都添加到array中生成的。它并不修改array。如果要进行concat()操作的参数是一个数组,那么添加的是数组中的元素,而不是数组。
      var a = [1,2,3];
        a.concat(4, 5);    // Returns [1,2,3,4,5]
        a.concat([4,5]);    // Returns [1,2,3,4,5]
        a.concat([4,5], [6,7]);    // Returns [1,2,3,4,5,6,7]
        a.concat(4,[5, [6,7]]);    // Returns [1,2,3,4,5,[6,7]]
    1 4 4
    join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 1 3 4
    pop() 删除并返回数组的最后一个元素 1 4 5.5
    push() 向数组的末尾添加一个或更多元素,并返回新的长度。 1 4 5.5
    reverse() 颠倒数组中元素的顺序。 1 3 4
    shift() 删除并返回数组的第一个元素 1 4 5.5
    slice() 从某个已有的数组返回选定的元素 1 4 4
    sort() 对数组的元素进行排序,有一个可选参数,为比较函数。 1 3 4
    splice() 删除元素,并向数组添加新元素。 1 4 5.5
    toSource() 代表对象的源代码 1 4 -
    toString() 把数组转换为字符串,并返回结果。 1 3 4
    toLocaleString() 把数组转换为本地数组,并返回结果。 1 3 4
    unshift() 向数组的开头添加一个或更多元素,并返回新的长度。 1 4 6
    valueOf() 返回数组对象的原始值 1 2 4

    Array 对象的属性

    方法 描述 FF N IE
    index   1 3 4
    input 在普通的Array中是不具备input属性的,只有在调用String对象的match()方法后返回的数组才具有input属性。它是用来存放匹配前的原字符串的内容。 1 3 4
    length 设置或返回数组中元素的数目。 1 2 4

    我们先来看数组克隆,现在公认用concat()来克隆数组的速度最快。下面做一些测试,分别为直接遍历复制,array.slice(0)与array.concat()

    判断一个变量引用的对象是否为数组。

    var isArray = function(a){
        return a &&
            typeof a === 'object' &&
            typeof a.length === 'number' &&
            typeof a.splice === 'function' &&
            !(a.propertyIsEnumerable('length'));
    }
    

    让数组具有计算能力,这个也很常用,不要用于财会的特殊报表中。

    Function.prototype.method = function(name,func){
        this.prototype[name] = func;
        return this;
    }
    Array.method('reduce',function(fn,value){
        for(var i=0,l=this.length;i<l;i++){
            value = fn(this[i],value);
        }
        return value;
    });
    

    如何使用,我们可以创建一个数字数组与相关的四则运算函数,把它们代入reduce函数中就行了

    var data = [4,8,10,12,16]
    var add = function(a,b){
        return a+b;
    }
    var mult = function(a,b){
        return a*b;
    }
    //使用
    var sum = data.reduce(add,0)
    var product = data.reduce(mult,1);
    

    each方法,让元素逐个执行传入的方法。JavaScript 1.6里已经实现了相应的forEach方法,但IE不支持,人们搞了个相近的each方法,在各大类库都有相应的实现。我们看一个漂亮的实现(作者为51JS的客服果果):

    Array.prototype.each = function(fn){
        for (var i=0;i <this.length;i++)
            this[i].constructor==Array?
            this[i].each(fn):
            fn.call(this[i],i);
    };
    
    [1,[2,[3,[4,[5,[6,[7,[8,[9,[0]]]]]]]]]].each(
        function(){
            return alert(this);
        });
    

    上面这个比较强大,除了能深层遍历数组外,还能遍历类数组对象(如arguments,NodeList),对象的所有属性都会被fn方法进行调用。但是从设计模式来看,它承担职责太多了.each方法就应该是面向数组,如果是对象或类数组对象,我们应该将它们转化为数组,如JQuery的makeArray,mootools和Prototype的$A。

      var arrayize = function(iterable){
        try{
          return Array.prototype.slice.call(iterable);
        }catch(e){
          var l = iterable.length || 0, array = new Array(l);
          while (l--) array[l] = iterable[l];
          return array;
        }
      }
    

    接着下来我们就可以实现纯数组的each函数了。

    var each = function(func, array) {
      for (var i=0,l = array.length; i<l; ++i) {
          func(array[i])
      }
    }
    

    然后再改成一个原型方法

    Array.prototype.each = function(func) { each(func,this); };
    

    不过,如果浏览器支持javascript1.6的forEach方法,就用forEach

    Array.prototype.each = function(func) {
        if(Array.prototype.forEach){
           this.forEach(func);
        }else{
            each(func,this); 
        }
    };
    

    用法:

    [4, 5, 6].each(function(index) { alert(index + "+2 = " + (index+2)); })
    

    火狐官网还有一个实现:

    if (!Array.prototype.forEach)
    {
      Array.prototype.forEach = function(fun /*, thisp*/)
      {
        var len = this.length >>> 0;
        if (typeof fun != "function")
          throw new TypeError();
    
        var thisp = arguments[1];
        for (var i = 0; i < len; i++)
        {
          if (i in this)
            fun.call(thisp, this[i], i, this);
        }
      };
    }
    

    让我们看一下jQuery提供的each方法的具体实现

     jQuery.each(obj,fn,arg)   

    该方法有三个参数:进行操作的对象obj,进行操作的函数fn,函数的参数args。

    让我们根据ojb对象进行讨论:

    1.obj对象是数组

    each方法会对数组中子元素的逐个进行fn函数调用,直至调用某个子元素返回的结果为false为止,也就是说,我们可以在提供的fn函数进行处理,使之满足一定条件后就退出each方法调用。当each方法提供了arg参数时,fn函数调用传入的参数为arg,否则为:子元素索引,子元素本身。

    2.obj 对象不是数组

    该方法同1的最大区别是:fn方法会被逐次不考虑返回值的进行进行。换句话说,obj对象的所有属性都会被fn方法进行调用,即使fn函数返回false。调用传入的参数同1类似。

    jQuery.each=function( obj, fn, args ) { 
        if ( args ) { 
           if ( obj.length == undefined ){ 
               for ( var i in obj ) 
                 fn.apply( obj, args ); 
           }else{ 
               for ( var i = 0, ol = obj.length; i < ol; i++ ) {
                  if ( fn.apply( obj, args ) === false ) 
                      break; 
              }
           }
       } else { 
           if ( obj.length == undefined ) {
                for ( var i in obj ) 
                   fn.call( obj, i, obj ); 
           }else{ 
              for ( var i = 0, ol = obj.length, val = obj[0]; i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} 
           }
      } 
      return obj; 
    }  
    

    需要特别注意的是each方法中fn的具体调用方法并不是采用简单的fn(i,val)或fn(args),而是采用了fn.call(val,i,val)或fn.apply(obj.args)的形式,这意味着,在你自己的fn的实现中,可以直接采用this指针引用数组或是对象的子元素。这种方式是绝大多数jQuery所采用的一种实现方式。

     Array.prototype.contains = function (obj) {
          return this.indexOf(obj) != -1;
        };
    
        Array.prototype.copy = function (obj) {
          return this.concat();
        };
    
        Array.prototype.insertAt = function (obj, i) {
          this.splice(i, 0, obj);
        };
    
        Array.prototype.insertBefore = function (obj, obj2) {
          var i = this.indexOf(obj2);
          if (i == -1)
            this.push(obj);
          else
            this.splice(i, 0, obj);
        };
    
        Array.prototype.removeAt = function (i) {
          this.splice(i, 1);
        };
    
        Array.prototype.remove = function (obj) {
          var i = this.indexOf(obj);
          if (i != -1)
            this.splice(i, 1);
        };
    
    //数组去重
    //2010.12.22
    function uniq1(array) {
        var n = array.length;
        for (var i = 0; i < n - 1; i++)
            for (var j = i + 1; j < n;)
                if (array[i] === array[j]) {
                    array.splice(j, 1);
                    n--;
                }else{
                    j++;
                }
        return array;
    }
    
    function uniq2(array) {
        var result = [], k = 0,n = array.length;
        for (var i = 0; i < n; i++) {
            for (var j = i + 1; j < n; j++)
                if (array[i] === array[j])
                    j = ++i;
            result[k++] = array[i];
        }
        return result;
    }
    
    //逐个移除数组里的元素
          var array = ["a","b","c","d"];
          for(var i=0;i < array.length;i++){
            array.splice(i--,1);
          }
          alert(array)
    

    相关链接:

    数组的扩展

  • 相关阅读:
    《面向模式的软件体系结构1模式系统》读书笔记(7) 通信
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(5) 截取器
    Enum variable is used in switch sentencejava Anny
    How to create a dynamic range source(转) Anny
    Managing Range Names in Excel 2010(转) Anny
    Mixed Content Handling Issue on IE7/8 Anny
    How to resolve "skip non existing resourceDirectory" when using "mvn test" Anny
    Install chinese input method in Ubuntu12.04 Anny
    IDL(International Date Line) Anny
    Web Accessibility508(转) Anny
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1555891.html
Copyright © 2020-2023  润新知