数组、对象、类数组对象的不同以及类数组转数组方法总结

一、数组、对象、类数组对象数据结构的异同

1、数组
一组有序的数据集合,其索引为从0开始且自然增长的整数,其元素值可以是任何js数据!并且包含一个名为length的属性,该属性表示数组元素的个数!

var array = [1,2,3];
console.log(array[0])//1
​console.log(array[1])//2
​console.log(array[2])//3
​console.log(array['length'])//3

ps:数组元素的索引和length属性是在数组定义时根据数组元素语言自动就帮你定义好了!

2、对象
一组无序的由键->值组成的数据集合,其元素的键名和值都可以自定义!

var object = {'a': 1, 'b': 2}
console.log(object['a'])//1
console.log(object['b'])//2
console.log(object['length'])//undefined

ps:对象自身所拥有的(不包括继承来的)任何属性都是有用户自定义的!

完全可以使用对象来模拟数组,只要我们定义的对象的每个元素的键名都使用数字并且让其保持递增,且动态的定义一个length属性来表示元素个数。

3、类数组对象
(1)什么是类数组对象

  • 拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)
  • 不具有数组所具有的方法
//类数组示例
var a = {'1':'gg','2':'love','4':'meimei',length:5};
Array.prototype.join.call(a,'+');//'+gg+love++meimei'

//非类数组示例
var c = {'1':2};   //没有length属性就不是类数组

ps:

  • 在浏览器环境中,NodeListHTMLCollectionNamedNodeMap都是类数组对象。关于这三者的不同请参考:javascript中的动态集合——NodeList、HTMLCollection、NamedNodeMap
  • 在function调用中,function代码内的arguments变量(保存传入的参数)也是一个类数组对象。
  • 在ECMAScript 5标准中,字符串string就是一个只读的类数组对象。

(2)判断一个对象是不是类数组

function isArrayLike(o) {
    if (o &&                                // o is not null, undefined, etc.
        typeof o === 'object' &&            // o is an object
        isFinite(o.length) &&               // o.length is a finite number
        o.length >= 0 &&                    // o.length is non-negative
        o.length===Math.floor(o.length) &&  // o.length is an integer
        o.length < Math.pow(2,32);              // o.length < 2^32
        return true;                        // Then o is array-like
    else
        return false;                       // Otherwise it is not
}

(3)类数组转换成数组之后进行操作有什么优势
由于类数组不具有数组所具有的操作数组的方法,讲类数组转换为数组之后就能调用如shift,unshift,splice,slice,concat,reverse,sort等这些强大的方法,方便快捷。
(4)类数组转换成数组的方法

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// 1. slice
Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"] 
// 2. splice
Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"] 
// 3. ES6 Array.from
Array.from(arrayLike); // ["name", "age", "sex"] 
// 4. apply
Array.prototype.concat.apply([], arrayLike)

ps:

Array.prototype.slice.call(arguments,1)

这句话的意思就是说把调用方法的参数截取出来。

function test(a,b,c,d) 
   { 
      var arg = Array.prototype.slice.call(arguments,1); 
      alert(arg); 
   } 
   test("a","b","c","d"); //b,c,d

所以其后面可以直接调用数组具有的方法,例如

Array.prototype.slice.call(arrayLike).forEach(function(element,index){  //可以随意操作每一个element了 })
  • Array.prototype.slice表示数组的原型中的slice方法。注意这个slice方法返回的是一个Array类型的对象
//slice的内部实现
Array.prototype.slice = function(start,end){  
      var result = new Array();  
      start = start || 0;  
      end = end || this.length; //this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键  
      for(var i = start; i < end; i++){  
           result.push(this[i]);  
      }  
      return result;  
 } 
  • 能调用call的只有方法,所以不能用[].call这种形式,得用[].slice。而call的第一个参数表示真正调用slice的环境变为了arrayLike对象。所以就好像arrayLike也具有了数组的方法。

    补充:将函数的实际参数转换成数组的方法:
    (1)var args = Array.prototype.slice.call(arguments);
    (2)var args = [].slice.call(arguments, 0);
    (3)var args = [];
    for (var i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
    }

    转换成数组的通用函数:

var toArray = function(s){  
    try{  
        return Array.prototype.slice.call(s);  
    } catch(e){  
            var arr = [];  
            for(var i = 0,len = s.length; i < len; i++){  
                //arr.push(s[i]);  
                 arr[i] = s[i];     //据说这样比push快
            }  
             return arr;  
    } 

(5)调用数组方法
如果类数组就是任性的想用数组的方法怎么办呢?
既然无法直接调用,我们可以用 Function.call 间接调用:

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }

Array.prototype.join.call(arrayLike, '&'); // name&age&sex

Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"] 
// slice可以做到类数组转数组

Array.prototype.map.call(arrayLike, function(item){
    return item.toUpperCase();
}); 
// ["NAME", "AGE", "SEX"]

(6) 将数组转换为参数列表(类数组)
调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合, 这里就说明apply的一个巧妙用法,可以将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 (param1,param2,param3), 这个如果让我们用程序来实现将数组的每一个项,来转换为参数的列表,可 能都得费一会功夫,借助apply的这点特性,所以就有了以下高效率的方法。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值