在JavaScript中,除了5种原始数据类型之外,其他所有的都是对象,包括函数(Function)。
基本数据类型:String,boolean,Number,Undefined, Null
引用数据类型:Object(Array,Date,RegExp,Function)
在这个前提下,咱们再来讨论JavaScript的对象。
1、创建对象
1 2 |
|
更多创建对象的知识,参见《JavaScript权威指南(第6版)》第6章
2、创建数组
1 2 |
|
更多创建数组的知识,参见《JavaScript权威指南(第6版)》第7章。
3、对象与数组的关系
在说区别之前,需要先提到另外一个知识,就是JavaScript的原型继承。所有JavaScript的内置构造函数都是继承自 Object.prototype。在这个前提下,可以理解为使用 new Array() 或 [] 创建出来的数组对象,都会拥有 Object.prototype 的属性值。
对于题主的问题意味着:
1 2 3 4 |
|
可以得到对象和数组的第一个区别:对象没有数组Array.prototype的属性值
4、什么是数组
数组具有一个最基本特征:索引,这是对象所没有的,下面来看一段代码:
1 2 3 4 5 6 7 8 9 10 |
|
通过上面这个测试,可以看到,虽然 obj[2]与arr[2] 都输出'a',但是,在输出length上有明显的差异,这是为什么呢?
obj[2]与arr[2]的区别
-
obj[2]输出'a',是因为对象就是普通的键值对存取数据
-
而arr[2]输出'a' 则不同,数组是通过索引来存取数据,arr[2]之所以输出'a',是因为数组arr索引2的位置已经存储了数据
obj.length与arr.length的区别
-
obj.length并不具有数组的特性,并且obj没有保存属性length,那么自然就会输出undefined
-
而对于数组来说,length是数组的一个内置属性,数组会根据索引长度来更改length的值。
为什么arr.length输出3,而不是1呢?
-
这是由于数组的特殊实现机制,对于普通的数组,如果它的索引是从0开始连续的,那么length的值就会等于数组中元素个数
-
而对于上面例子中arr,在给数组添加元素时,并没有按照连续的索引添加,所以导致数组的索引不连续,那么就导致索引长度大于元素个数,那么我们称之为稀疏数组。
有关稀疏数组的特性就不再讨论更多,参见《JavaScript权威指南(第6版)》7.3节。
5、伪数组
定义:
1、拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)
2、不具有数组所具有的方法
伪数组,就是像数组一样有 length
属性,也有 0
、1
、2
、3
等属性的对象,看起来就像数组一样,但不是数组,比如
1 2 3 4 5 6 7 8 9 10 11 12 |
|
常见的参数的参数 arguments,DOM 对象列表(比如通过 document.getElementsByTags 得到的列表),jQuery 对象(比如 $("div"))。
伪数组是一个 Object,而真实的数组是一个 Array
1 2 3 4 5 6 |
|
《javascript权威指南》上给出了代码用来判断一个对象是否属于“类数组”。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
不过有个更简单的办法来判断,用 Array.isArray
1 2 |
|
从外观上看伪数组,看不出来它与数组的区别,在JavaScript内置对象中常见的伪数组就是大名鼎鼎的auguments:
1 2 3 |
|
另外在DOM对象中,childNodes也是伪数组
1 |
|
除此之外,还有很多常用的伪数组,就不一一列举。
伪数组存在的意义,是可以让普通的对象也能正常使用数组的很多算法,比如:
1 2 3 4 5 6 7 8 |
|
除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用[].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。
1 2 3 4 5 6 7 8 |
|
将具有length属性的对象转换成数组对象,arguments是每个函数在运行的时候自动获得的一个近似数组的对象(传入函数的参数从0开始按数字排列,而且有length)。
比如当你 func('a', 'b', 'c') 的时候,func里面获得的arguments[0] 是 'a',arguments[1] 是 'b',依次类推。但问题在于这个arguments对象其实并不是Array,所以没有slice方法。Array.prototype.slice.call( )可以间接对其实现slice的效果,而且返回的结果是真正的Array。
对于IE9以前的版本(DOM实现基于COM),我们可以使用makeArray来实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
更多关于伪数组的知识,参见《JavaScript权威指南(第6版)》7.11节。
6、总结
-
对象没有数组Array.prototype的属性值,类型是Object,而数组类型是Array;
-
数组是基于索引的实现,length会自动更新,而对象是键值对;
-
使用对象可以创建伪数组,伪数组可以正常使用数组的大部分方法;