林大妈的JavaScript基础知识(三):JavaScript编程(4)数组
数组,是一段线性分配的,具有非常高性能的数据结构。简单地说,数组以连续的空间存储,通过整数地计算偏移量访问其中的元素,将读取修改的时间复杂度降低至O(1),我们称之为猝发式存取。是不是非常期待?没错,像这样的好东西,JavaScript没有。
1. Array简介
但作为替代,JavaScript设计者想出了一个更方便但性能相对较低的方案,打印观察Array.prototype,会发现,设计者为我们提供的是一个array-like(类数组)的对象。在检索和更新属性上,Array就和普通的对象一模一样(也就是说要遍历所有属性),只是多了一个不可枚举的属性length来记录这个对象所表示的数组的长度。尽管Array对象的性能明显比数组要差,但是搭配上弱类型的JavaScript语言(当然,JavaScript中不存在传统的数组一部分原因也是因为这一点),它在使用上非常的方便。更贴心的是,设计者还为我们提供了许多内置的方法,可以快速解决其他语言费很大劲才能解决的问题。
2. 声明
数组的声明跟对象的声明很类似。我们可以用两种方法初始化一个数组:① 直接用 var array = []; 我们称之为数组字面量的方式来初始化;② 使用构造函数 var array = new Array(); 如果参数填入一个数字,则返回一个长度为这个数字的空数组,如果参数填入多个值,则返回一个按顺序保存了这些值的Array对象。
3. 修改
上面我们已经搞清楚了Array对象总体的结构,这样修改一个数组就可以转化为我们以前学到的修改一个对象属性的知识了。由于JavaScript的灵活性,除非你定义一个大到Infinity的数组,其他情况下均不会因为越界报错(Runtime Error也许是很多人的噩梦,反正是我的噩梦)。因此,假如我们现在有这样一个数组:
var myArray = [0, '1', true]
利用JavaScript会帮我们维护length属性这一特点(但为了编写易维护的代码,不推荐这些简单粗暴的做法),我们也可以做一些在别的语言中看起来不可思议的操作,例如:① myArray[8] = undefined 会直接把Array的长度扩展到8;② myArray.length = 0; 能直接清空数组。除了可以这样清空数组,还可以通过Array.prototype.splice方法完成清空,因此我们把目光放到数组的原型方法上来。
4. 原型方法(均以上面的myArray举例)
① indexOf
indexOf方法同时存在于Array.prototype和String.prototype中,可以用它来检测数组或字符串中是否存在对应的元素,如果存在,则返回它的下标,如果不存在,则返回-1:
console.log(myArray.indexOf(0)); //0 console.log(myArray.indexOf(1)); //-1
由于在数组中,1和'1'是两个不同的值,因此第二句返回结果-1。
② push、pop、unshift、shift
push朝数组末尾推入若干新元素,返回加入后数组的length。
pop弹出数组末尾的一个元素,返回被弹出的元素。
unshift朝数组开头推入若干新元素,返回加入后数组的length。
shift弹出数组开头的一个元素,返回被弹出的元素。
console.log(myArray.push('A', 'B')); //5 console.log(myArray.pop()); //'B' console.log(myArray.unshift('A', 'B')); //6 console.log(myArray.shift()); //'A'
③ sort(这时候我们重新定义一下 myArray = [5, 2, 0, 10, 17, 25]; )
sort方法在原数组上动刀,这里我们期望将数组中的数按从小到大的顺序排列,sort函数可以帮我们做到这一点,但需要注意的是,sort函数默认把这些元素转化为字符串进行比较。因此这个数组排序以后的结果是这样的:
console.log(myArray.sort()); // [0, 10, 17, 2, 25, 5]
因此通常需要填入一个比较判断函数作为参数,下面传入一个箭头函数,按照我所定义的这个函数进行判断大小再排序:
console.log(myArray.sort((x, y)=>{return x - y;})); // [0, 2, 5, 10, 17, 25]
④ reverse和join
reverse方法在原数组上动刀,返回跟原来相反的数组;join方法相当于String.prototype.split方法的反函数,填入一个字符串参数,以这个参数将每个元素分隔开,合并成一个字符串并返回。这两个方法可以搭配使用来处理反向输出字符串的问题:
var str = "Hello world!"; console.log(str.split('').reverse().join('')); //"!dlrow olleH" console.log(str.split(' ').reverse().join(' ')); //"world! Hello"
这里由于每个函数返回值都是与其相对应的数组或字符串,可以直接在这个返回值上进行操作,因此我们还用到了链式调用的技巧。
⑤ slice和splice
这两个方法的区别和使用非常重要,又由于它们名字之间只差一个字母,缺少练习时我们很容易会将其混淆。
slice方法可以类比String.prototype.substring。指定一个参数n,它将返回一个新数组,这个数组中含有原数组下标从n到末尾的所有元素。指定两个参数a和b时,它将返回一个新数组,这个数组含有原数组下标从a到b的所有元素(不得不说,用中文来描述真的非常蹩脚):
var myArray = [1, 2, 3, 4, 5, 6, 7, 8]; var aNewArray = myArray.slice(3); var aNewNewArray = myArray.slice(3, 5); console.log(aNewArray); //[4, 5, 6, 7, 8] console.log(aNewNewArray); //[4, 5]
当然了,这两种操作都是含头不含尾的。如果不指定参数地使用slice,它将返回一个跟原数组一模一样的数组,利用这一点,我们可以用一句代码复制一个数组。
splice是修改一个数组的“万能方法”,要注意它将直接在原数组上动刀,返回值是被删除的元素组成的数组:
var myArray = ['CapAmerica', 'IronMan', 'Hulk', 'Thor']; // param: 从第4个元素开始操作,删除0个元素,加入新元素'BlackWidow' myArray.splice(3, 0, 'BlackWidow'); // 由于删除0个元素,它将返回一个空数组 console.log(myArray); // ['CapAmerica', 'IronMan', 'Hulk', 'Thor', 'BlackWidow'] // param:从第二个元素开始,删除三个元素,加入这些新元素 myArray.splice(2, 3, 'ScarletWitch', 'Vision', 'CapMarvel'); //返回['Hulk', 'Thor', 'BlackWidow'] console.log(myArray); //['CapAmerica', 'IronMan', 'ScarletWitch', 'Vision', 'CapMarvel']
⑥ concat
concat方法不会动原数组,而是返回新数组。它返回一个将原数组和所有你填入的参数都合并在一起的新数组,因此我们想到了可以用它搭配splice方法来实现一个JavaScript版本的快速排序:
function quickSort(arr) { if(arr.length <=1) return arr; var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < pivot) left.push(arr[i]); else right.push(arr[i]); }; return quickSort(left).concat(pivot, quickSort(right)); }
总结:① JavaScript中的Array对象只是一个内建的对象,并不是传统意义上的数组,它在内存中不是连续的空间,因此只能遍历元素来进行查找修改,性能较差但灵活性非常好。
② Array.prototype中有非常多的方法,常用的有以上这些:indexOf、push、pop、unshift、shift、sort、reverse、join、slice、splice和concat。还有很多其他的方法,要善用这些方法只能靠多练习,慢慢积累。
- 林大妈的JavaScript基础知识(三):JavaScript编程(1)对象
- PHP编程中数组的基础知识(转自http://info.codepub.com/2008/08/info-21593.html)
- 前端JavaScript基础知识点讲义代码九九乘法表、函数、排序、数组、循环、分支判断、对象、日期函数、装饰器、闭包、堆和栈、字符串
- PHP编程“数组”的基础知识
- Javascript基础知识盲点总结——数据类型和数组
- 源码-JavaScript&jQuery交互式前端开发-第1章-编程基础知识
- 入门:PHP编程“数组”的基础知识
- javascript基础知识梳理-数组
- java基础64 JavaScript中的Arrays数组对象和prototype原型属性(网页知识)
- 编程基础知识——C/C++字符串和字符数组
- javascript基础知识和Dom编程学习
- 一个大型例子搞定 Javascript 的数组基础知识 ——总结《Javascript 权威指南》第六版数组基础知识
- JavaScript基础知识整理(1)数组
- Javascript 基础知识 - 数组
- 林大妈的JavaScript基础知识(二):编写JavaScript代码前的一些简单工作
- javascript学习篇之对象和数组创建等基础知识代码笔记
- Javascript & DHTML 实例编程(教程)基础知识
- 【知识整理】javascript基础语法总结(5)——数组
- PHP编程中“数组”的基础知识
- 编程基础知识之数组