javascript中类数组对象的相关知识
一、javascript类数组对象
可以把 arguments 转化为数组:[].slice.call(arguments),因为
arguments 是个类数组对象,所以才可以这么用。
一直不清楚什么叫做类数组对象( array-like objects)
例子:
前面那几个是操作字符串的,嗯,字符串也可以看成类数组对象。但是后面那个 b 对象居然
也是类数组对象。
书上的解释:
So what exactly makes an object “array-like”? The basic contract of
an array object alinuxjishu/9952.html target=_blank class=infotextkey>mounts to two simple rules.
It has an integer length property in the range 0...2^32 – 1.
The length property is greater than the largest index of the object.
An index is an integer in the range 0...2^32 – 2 whose string representation
is the key of a property of the object.
居然只有这两条简单的规则。
所以为什么 arguments, 字符串,和上面那个 b 对象可以看作类数组对象呢?
它们都有一个合法的 length 属性(0 到 2**32 - 1 之间的正整数)。
length 属性的值大于它们的最大索引(index)。
例子:
不对了,成了'ab' 了,因为违反了规则2:length 属性是3,
最大索引值是4要比 length 属性大了。所以表现的不正常了。
太强大了,好像只是定义了一个接口,只要符合这个接口,就可以利用数组的所有方法。
其实不是可以利用所有方法,Array.prototype.concat
是不能用的,因为它是把两个数组连接起来,你不是数组肯定是没法用它的。
还有一个小问题是,字符串创建以后是不可变的(immutable),所以你怎么折腾它都是不可变的。
但是这本书根本就没有解释为什么是符合这两个条件就可以看成类数组对象,另外这本书的作者
是那个什么 ECMAScript 委员会的成员,所以基本还是可信的。
至于为什么符合这两个条件就可以看成是类数组对象,我也不知道,谷歌搜了半天也没看到什么合理的解释。
二、javascript对象和数组用法技巧
javascript1.2之后允许使用[]创建数组:
可以在数组创建后添加元素:
这样的结果是第4个元素和第2个元素之间有1个空元素。
结果类似这样:["red", "green", "blue",,28]
注意,数组必须初始化,我测试了数组作为数组元素的定义:
本来设想实现二维数组,结果是使用arrArray[i][0]当i>0时无效!
其实是定义了arrArray[0]为一个空数组,而其他元素都未定义,相当于
所以arrArray[1]没有定义,所以如果将它作为数组进行操作会出错。
删除一个数组元素:delete
delete的结果是myColors[1]=undefined,但是myColors.length不变,myColors变成这样:["red",, "blue"]
替换或绝对删除数组元素用slice():
var myArray = [1, 2, 3, 4, 5];
myArray.slice(2); // returns [3, 4, 5]
myArray.slice(1, 3); // returns [2, 3]
myArray.slice(-3); // returns [3, 4, 5]
myArray.slice(-3, -1); // returns [3, 4]
myArray.slice(-4, 3); // returns [2, 3]
myArray.slice(3, 1); // returns []
var myArray = [1, 2, 3, 4, 5];
myArray.splice(3,2,''a'',''b'');
// returns 4,5 [1,2,3,''a'',''b'']
myArray.splice(1,1,"in","the","middle");
// returns 2 [1,"in","the","middle",3,''a'',''b'']
数组是传递引用的!
你猜结果是多少呢?
// Declare a reference type (array)
var refType = ["first ", " second", " third"];
// Declare a primitive type (number)
var primType = 10;
// Declare a function taking two arguments, which it will modify
function modifyValues(ref, prim)
{
ref[0] = "changed"; // modify the first argument, an array
prim = prim - 8; // modify the second, a number
}
// Invoke the function
modifyValues(refType, primType);
// Print the value of the reference type
document.writeln("The value of refType is: ", refType+"<
>");
// Print the value of the primitive type
document.writeln("The value of primType is: ", primType);
测试时发现一个问题:
弹出的数字是0!
看了文档后知道,这样的数组叫做联合数组(Associative Arrays),arr['a']等同于arr.a,arr.length也就等同于arr['length'],而arr.length在我们初始化arr(var arr=[];)的时候自动赋值为0。
有人把这种联合数组叫做javascript的hash table。严格上讲,联合数组和普通数组本身都是对象(废话,javascript中的一切都是对象- -),意义和用法都是相同的。看下面的例子:
var arr=[];
arr=[1,2,3];
arr.test='test';
alert(arr);
alert(arr[1]);
alert(arr['test']);
var arr={}; arr=[2,3,4]; alert(arr[0]);
var arr={};和var arr=[]都可以写成var arr=function(){};
从上面的代码可以看出,下标数组跟联合数组分别独立,下标只作用于下标数组,不能访问联合数组,相应的,联合数组不对length属性产生影响。联合数组的标签就是属性,但是下标数组的下标并不是属性,arr[0]!=arr.0,访问arr.0会出错。
在某些时候,用arr['a']代替arr.a作为方法调用会更有效,因为arr['a']中的'a'可以用变量传入,比如将方法赋给变量:
这时用直接d.l就会出错,而用d[l]就可以正确执行,alert一下就知道了:)
既然数组是由lenght属性的对象,那么是不是所有具有length属性的对象都是数组呢?比如String。测试之后发现,firefox是可以把String当作数组处理的,但是ie不行:
数组的对象应该比较独特,用户对象不能完全模拟:
本以为Array的length属性就是普通的对象属性,结果经过上面的例子发现,arr的length不再是数组length,arr的结构也不是普通数组结构。
定义一个函数/类的方法有好几种:
function fName(arguments){
//function body
};
var fName = function(arguments){
//function body
}
var fName = new Function("arguments","/*function body*/");
第三种方法比较好玩,例子:
用这个方法可以解析ajax返回的JSON,这样就不用低效的eval了(没有测试是否比eval快):
假设{b:{c:2}}为返回的json字符串: