浅谈Javascript数组索引

从题目说起,之所以是不完全,是因为有些东西比如数组的方法怎么用这个我都不打算讲,因为那个看一下都会,下面讲的都是我觉得重要的,只关于数组对象本身。另外,由于我的Javascript实战经验不多,所以可能有些东西没涉及到,有些内容说的有误,请发现问题的同学不吝指教。

首先,Javascript(下称js)的数组定义,这不是重点,简单说下,下面两句都是创建一个空的数组:

  var arr = [];
  var arr2 = new Array(); // 不写new也可以。

在创建之后,你就可以随时往数组里添加元素。数组的大小是不固定的,可以像a[0] = 1这样随意添加。

然后到重点了,关于往数组里添加元素这件事。首先,你要知道数组是一个对象,而对象是一个键值对的集合(类似于java里面的map,python里面的dict,c#里面的Dictionary),对象可以有属性,对象的函数叫方法,对象的属性或方法可以使用方括号或点号的方式访问,其中使用方括号引用要加引号,点号的使用只有在属性名称是一个合法的变量名称的时候才可以使用,也就是属性不包含任何空格连字符并且不以数字开头时才可以,看个例子:

  var person = {};
  person.age = 22;
  person.sayhi = function(){console.log('hi');};

  person.age; // 22
  person['age']; // 22

  person.sayhi(); // hi
  person['sayhi'](); // hi

嗯,这就是对象,好像也没什么特别的(除了用方括号取值外),不过对象说些就够了,后面开始说数组。

对于上面的这些,数组全可以做到,也就是说,下面这段代码也可以正常运行(只有第一行跟上面的不一样):

  var person = [];
  person.age = 22;
  person.sayhi = function(){console.log('hi');};

  person.age; // 22
  person['age']; // 22

  person.sayhi(); // hi
  person['sayhi'](); // hi

因为数组就是对象,这里不要把方括号的字符串索引和通常讲的数字索引弄混了,还没开始说(马上说)数字索引呢。

和普通的对象不同,数组对象的元素有数字索引,或者说特殊的键(前面说了对象是键值对),这和我们在其他语言比如java、c#等语言中的见到的数组是一样的。在js中,这个键有一些特殊的要求,它可以是数字,也可以是能转换成数字的字符串,而合理的数字,需要是范围在0到4294967295(2^32-1)的整数(事实上,这个索引在词法分析的时候都是当做字符串的,js把这个字符串转换成32位的整数,然后再把32位的整数转换成字符串跟原字符串比较,如果相同的话,则说明这个索引值是合法的数字,否则就是一个普通的字符串键)。简单举个例子:

  a = [1, 3, 5, 7];
  console.log(a[0]); // 1
  console.log(a['0']); // 1

  a['2'] = 12;
  console.log(a[2]); // 12

上面的代码都是可以在浏览器里运行的,注释是输出值。这和我们在其他语言中见到的数组好像没啥区别。这个a['2'] = 12;因为'2'被转换成整数再转换成字符串还是'2',所以跟a[2]一样。不过其他语言里,我们使用数组都是定义一个固定大小数组的对不对?这里好像不是哈,而且这里还说了数组的索引范围。所以,为什么?简单点回答就是这里的数组是对象,是js中的对象。这一点和其他语言(python等函数式的除外)不同,具体哪里不同,我没深入研究,也说不太清楚,我理解的是,c/java等语言定义数组的时候,是在内存中划分了一块固定大小的区域,有一个指针存储着这块区域的首地址。而js中好像不是这样的,就像前面说的一样,数组是对象,键值对结构,所以我觉得js中的数组都是用hash的方式存储元素的,元素之间的内存不一定是连续的。不过我现在没找到查看js变量内存地址的方法,所以没法确定这件事。不过这不是本文要讲的重点。

我们把重点放到索引上,前面说了索引的范围,不过有同学可能试了,就是a[-1] = 2;或是a[4294967296] = 10;这种语句也没有问题。对的,这并不是错误,这是正常的语句,当然不会有问题。但是问题是前面不是说了索引必须是0到4294967295的整数么?对,是的,这也没错。那疑问出在哪里呢?

先贴两张firefox控制台的截图:


你有没有发现什么问题呢?当我们使用正常的索引添加元素,在打印数组的时候,添加的元素会被打印出来,而使用非正常的“索引”添加元素时,打印的数组里面却没有添加的元素,但是你看右侧的Array对象,所有添加的元素却一个不少。再看一张图,这次多添加几个元素,再给数组添加一个属性(注意看右侧Array对象的元素索引):

不知道你有没有发现。在右侧,上面几个是数字索引,打印数组的时候能被打印的,而下面几个是属性,打印数组不会打印属性!也就是说,a[-2] = 2;这种语句,这个-2是属性的键,而不是特殊的数字索引的键,-2在被强制转换成正整数的时候,被认为是一个字符串,所以这个-2和4294967296和'name'一样,都是数组的一个属性的键!所以前面说的负索引或是超出范围的索引(应该说是属性的键)都是合法的,它们都是普通的字符串键。

这里一个问题,就是既然说-2这种键是普通的属性键,那有人可能会说为什么使用a.-2或是a.'-2'访问-2这个键的值会报错,而a[-2]就不会报错?对呀,为什么?前面在讲对象的时候,有一句加粗的话:对象的属性或方法可以使用方括号或点号的方式访问,其中使用方括号引用要加引号,点号的使用只有在属性名称是一个合法的变量名称的时候才可以使用,也就是属性不包含任何空格连字符并且不以数字开头时才可以。所以,-2这种键的属性,是不能用点号的方式访问的!

另外还有一个小问题,就是方括号,当我们想访问数组的name属性的时候,需要这样:a['name'],也就是name被引号包起来了,而-2是和name一样的属性的键,为何-2可以不用(也可以用)引号包起来?其实,方括号内的所有字符会被当成一个表达式,单纯的一个数字-2,是个合法的表达式,但name如果没有被定义成变量名,name就不是合法的表达式,同样x^b&c这种也不是合法的,因为它会被当成变量x、b、c组成的某种表达式,但是x、b、c是不是变量还不确定,而且里面的符号不一定是被js所支持的,所以a[name]的问题出在name上,而不是[]上。如果还不好理解,你可以把name想象成x+y,在x、y没有被定义成变量的时候,x+y这个表达式肯定有问题对不对?那a[x+y]也会有问题对不对?而a['x+y']就没有问题,因为'x+y'是个字符串。

后面补充一点,js中,变量名字是可以由数字、字母、下划线任意组合的,其中数字不能放在开始位置。而对象的属性键的命名要宽松一些,合法的可以不用引号,不合法的用引号包起来就可以。

好了,说的差不多了,总结一下:文章首先简单介绍了下对象,然后说了数组也是对象,最后解释了下一些疑问,然后总结。

写这篇文章的原因是我昨天在微博里看了一条js的教程,对数组的讲解产生了一个疑问,然后评论的字数超出了140,所以我就查资料单独写出来了。目的是让自己弄明白,也愿能帮助到学js的同学。数组范围和索引转换那里是参考的《Speaking Javascript》,其他地方都是自己的理解和看法。

最后,感谢观看,因为是分两次写的,可能语句有些乱,有的地方不乱但是上下文也完整,有的上下文完整但是废话太多,总之,就这样吧。下篇见。

(0)

相关推荐

  • JavaScript中的索引数组、关联数组和静态数组、动态数组讲解

    数组分类: 1.从数组的下标分为索引数组.关联数组 复制代码 代码如下: /* 索引数组,即通常情况下所说的数组 */ var ary1 = [1,3,5,8]; //按索引去取数组元素,从0开始(当然某些语言实现从1开始) //索引实际上就是序数,一个整型数字 alert(ary1[0]); alert(ary1[1]); alert(ary1[2]); alert(ary1[3]);   /* 关联数组,指以非序数类型为下标来存取的数组  python中称为字典 */ var ary2 =

  • JavaScript 以对象为索引的关联数组

    关于JSON对象,你可以参看wikipedia(http://zh.wikipedia.org/zh-cn/JSON),还有官方网站(http://www.json.org/json-zh.html). 我们常说JavaScript原生支持json,因为我们可以认为json就是对JavaScript的Object对象的灵活应用. 通常我们使用json的方式,主要用作前后台数据交换的格式: 而在代码逻辑中更多的是用关联数组的方式.但即使是这样我们也很少使用对象类型作为键值对的键名. var a=

  • javascript实现随机读取数组的方法

    本文实例讲述了javascript实现随机读取数组的方法.分享给大家供大家参考.具体如下: function write_quote() { var quotes = [ 'no animals were harmed while making this page', 'made in ulm', 'this page was handmade', 'Get <a href="http://www.mozilla.org/products/firefox/">FireFox

  • JavaScript数组对象实现增加一个返回随机元素的方法

    本文实例讲述了JavaScript数组对象实现增加一个返回随机元素的方法.分享给大家供大家参考.具体如下: 核心特性: 概率随机.顺序随机.随机冒泡 本方法 来自个人手写 JavaScript 的实践,只涉及 JavaScript 1.5(ECMAscript 3 国际标准)语言本身,在所有 JS 引擎实现中通用~ 为Array对象新增random方法: (function () { function Random_SN(iArray) { return Math.floor(Math.rand

  • JavaScript数组随机排列实现随机洗牌功能

    本文实例讲述了JavaScript数组随机排列实现随机洗牌功能的方法.分享给大家供大家参考.具体分析如下: 这段JS代码可以对数组内的元素进行随机排列,这个非常有用,比如我们在玩扑克牌的时候可以让扑克牌进行排列,也就是电脑洗牌. var list = [1,2,3,4,5,6,7,8,9]; list = list.sort(function() Math.random() - 0.5); Print(list); // prints something like: 4,3,1,2,9,5,6,

  • JavaScript实现数组随机排序的方法

    本文实例讲述了JavaScript实现数组随机排序的方法.分享给大家供大家参考.具体实现方法如下: function Shuffle(o) { for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o; }; 使用方法: var testArray = [1,2,3,4,5]; Shuffle(testArray); // jQuery

  • javascript数组随机排序实例分析

    本文实例讲述了javascript数组随机排序实现方法.分享给大家供大家参考.具体如下: 我们就测试0-9的随机排序,先生成数据 var arr=[9,3,1,2,5,8,4,7,6,0]; arr.sort(); document.write("正常排序后的数组元素:"+arr.join(",")+"<BR />"); 正常排序后的数组元素:0,1,2,3,4,5,6,7,8,9 定义一个随机函数,随机返回正数或者负数,sort函数

  • JavaScript对数组进行随机重排的方法

    本文实例讲述了JavaScript对数组进行随机重排的方法.分享给大家供大家参考.具体如下: 这里提供了两个方法对数组进行随机重排. <script> var count = 100000,arr = []; for(var i=0;i<count;i++){ arr.push(i); } //常规方法,sort() var t = new Date().getTime(); Array.prototype.sort.call(arr,function(a,b){ return Math

  • javascript实现数组内值索引随机化及创建随机数组的方法

    本文实例讲述了javascript实现数组内值索引随机化及创建随机数组的方法.分享给大家供大家参考.具体如下: 今天在QW交流群里看到有同学讨论使数组随机化的问题,其中给出的算法很不错,让我想起了之前自己实现过的不怎么"漂亮"的方法.想想我们有时候在繁忙的写业务代码时只是为了实现其功能,并未花太大心思去思考是否有更好的实现方法. 就这个数组问题(随即排序一个数组里的值,返回一个新数组)来说,我以前的实现方法是这样的: function randArr(arr) { var ret =

  • JavaScript通过元素索引号删除数组中对应元素的方法

    本文实例讲述了JavaScript通过元素索引号删除数组中对应元素的方法.分享给大家供大家参考.具体分析如下: JavaScript通过元素的索引号删除数组中的元素,如果要删除第3个元素,则使用RemoveValByIndex(2)即可,JS数组从0开始 function RemoveValByIndex(arr, index) { arr.splice(index, 1); } test = new Array(); test[0] = 'Apple'; test[1] = 'Ball'; t

随机推荐