目录
8、数组
8.1 数组基础
8.1.1 创建数组
8.1.2 读写数组
8.1.3 数组元素
8.1.4 数组复制
8.2 数组方法
8.2.1 查找/转换/拼接/截取
1. 查找元素
2. 数组与字符串转换
3. 数组的拼接和截取
8.2.2 增删函数
8.2.3 排序函数
8.2.4 迭代器方法
1、不生成新数组 的迭代器方法
2、生成新数组 的迭代器方法
8.2.5 累加方法
8.2.6 类型判断
8.3 类数组
8.4 二维和多维数组
创建二维数组
处理二维数[[1,2],[3,4]]
参差不齐的数组
JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引只能是整数。然而,这些数字索引在内部被转换为字符串类型,这是因为 JavaScript 对象中 的属性名必须是字符串。数组在JavaScript中只是一种特殊的对象,所以效率上不如其他 语言中的数组高。
JavaScript 中的数组,严格来说应该称作对象,是特殊的 JavaScript 对象,在内部被归类为数 组。由于 Array 在 JavaScript 中被当作对象,因此它有许多属性和方法可以在编程时使用。
// Array .prototype.proto===Object.prototype
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 | ||
pop() 删除并返回数组的最后一个元素 | ||
push() 向数组的末尾添加一个或更多元素,并返回新的长度。 | ||
reverse() 颠倒数组中元素的顺序。 | ||
shift() 删除并返回数组的第一个元素 | ||
slice() 从某个已有的数组返回选定的元素 | ||
sort() 对数组的元素进行排序 | ||
splice() 删除元素,并向数组添加新元素。 | ||
toSource() 返回该对象的源代码。 | ||
toString() 把数组转换为字符串,并返回结果。 | ||
toLocaleString() 把数组转换为本地数组,并返回结果。 | ||
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。 | ||
valueOf() 返回数组对象的原始值
|
创建数组的基本方式有两种。
(1) 第一种是使用Array构造函数:
var colors1 = new Array(); //定义空数组 var colors2 = new Array(20); //定义长度为20的数组 var colors2 = new Array(20,10); //定义[20,10] var colors2 = new Array("hello"); //定义[hello]
(2) 第二种方式是使用数组字面量表示法:
var colors = ['red','blue','green']; var names = [];
推荐使用 [] 操作符,和使用Array的构造函数相比,编写代码的速度更快,效率更高。
写--使用 [] 操作符将数据赋给数组:
var nums = []; nums[0] = 1; //通过[]操作符赋值 for (var i = 0; i < 100; ++i) { nums[i] = i+1; }
读--使用 [] 操作符读取数组中的元素:
var h=0 var arr6 = new Array({x:1, y:2}, h+5, h+9); console.log(arr6[0]);
length属性反映的是当前数组中元素的个数,使用它,可以确保循环遍历了数组中的所有元素。
JavaScript 中 的数组也是对象,数组的长度可以任意增长,超出其创建时指定的长度。数组元素不连续的数组我们称为稀疏数组:
var arr=[1,2,4,,6] var arr = new Array(5); arr[10] = 6; arr[100] = 56; console.log(arr); console.log(arr.length);
元素的添加: (改变原数组)
(a) 使用 [] 操作符;
(b) arr.push(val),在数组末尾添加元素;
(c) arr.unshift(val),在数组开头添加元素
区别:[]执行完毕,返回所添加的元素值;push()/unshift()执行完毕后返回新数组长度
var arr = ['h', 'q', 'y', 'j']; arr[4] = 'five'; //['h', 'q', 'y', 'j',"five"] arr.push('one');//['h', 'q', 'y', 'j',"five","one"] arr.push('two_1', 'two_2');//['h', 'q', 'y', 'j',"five","one",'two_1', 'two_2'] arr.unshift('first');//['first','h', 'q', 'y', 'j',"five","one",'two_1', 'two_2'] arr.unshift('first_1', 'first_2'); // //数组的长度是最后一个元素的下标+1 var arr=[10,20,,,,30] console.log(arr) //(6) [10, 20, 空属性 × 3, 30] var arr=[10,230,54] var re=arr.unshift(100,200) console.log(re,arr) //5 (5)[100, 200, 10, 230, 54]
元素的删除 (改变原数组)
(a) delete arr[i]操作
(b) arr.pop() 删除数组最后一个元素
(c) arr.shift() 删除第一个元素
区别:
delete执行完毕返回true或false,只删除元素值不会改变数组长度;
pop()/shift()执行完毕返回删除的数组元素(返回新数组)(可能是空数组,因为最开始就是空的),改变数组长度var arr=[10,230,54] var re=arr.pop() arr.pop() arr.pop() // console.log(re,arr) //54 [] var re2=arr.pop() console.log(re2,arr) //und []
遍历数组元素
for循环对数组元素进行遍历:
var numbers = [1,2,3,5,8,13,21];
var sum = 0;
for (var i = 0; i < numbers.length; ++i) {
sum += numbers[i]; //通过[]操作符读取
}
console.log(sum);
将一个数组赋给另外一个数组,有两种方式,分别为浅复制和深复制。
浅复制
var nums = []; for (var i = 0; i < 100; ++i) { nums[i] = i+1; } var samenums = nums; nums[0] = 400; console.log(samenums==nums)//true console.log(samenums[0]);这种行为被称为浅复制,新数组依然指向原来的数组。
深复制
var nums = []; for (var i = 0; i < 100; ++i) { nums[i] = i+1; } var samenums=[]; var length =nums.length; //数组长度 for(var i=0;i
//所有数组的方法,返回了一个新数组,新数组中的元素,如果是以前数组中的引用数据,那么是同一个引用
var arr=[{name:"karen"},100,200,4]
var arr2=[1,2,3,4,5]
var re=arr.concat(arr2,90,20)
//arr和arr2和re都不相等
re[0].name="jack"
console.log(arr) //arr里面的name也改为jack了
JavaScript 提供了一组用来访问数组元素的函数,叫做存取函数
该小节也可称之为”存取函数“。
(1) indexOf(val)
indexOf(val) 函数是最常用的存取函数之一,用来查找传进来的参数在目标数组中是否存在。如果目标数组包含该参数,就返回该元素在数组中的索引;如果不包含,就返回 -1。
var names = ["David", "Cynthia", "Raymond", "Clayton", "Jennifer"]; var position = names.indexOf('Cynthia');如果数组中包含多个相同的元素,indexOf()函数总是返回第一个与参数相同的元素的索引
(2) lastIndexOf(val)
lastIndexOf(val),该函数返回相同元素中最后一个元素的索引,如果没找到相同元素,则返回 -1。
var names = ["David", "Mike", "Cynthia", "Raymond", "Clayton", "Mike", "Jennifer"]; var name = "Mike"; var lastPos = names.lastIndexOf(name);
(1) 有两个方法可以将数组转化为字符串:
join() 不传参,就默认是逗号。传参就是将数组中每一个元素toString(),(对象toString后是:[obejct obejct])然后进行拼接 此方法只有数组才有
toString() :用逗号连接数组的toString()就相当于join方法 此方法都有
这两个方法都返回一个包含数组所有元素的字符串,各元素之间用逗号分隔开。
var names = ["David", "Cynthia", "Raymond", "Clayton", "Mike", "Jennifer"];
var namestr = names.join('-');
console.log(namestr); //David-Cynthia-Raymond-Clayton-Mike-Jennifer
namestr = names.toString();
console.log(namestr);//David,Cynthia,Raymond,Clayton,Mike,Jennifer
var arr=[10,2,3,4,44,[90,10],{name:"karen"}]
var re=arr.join("*") //不传参数默认是, 传参 把数组中每一个元素toString()然后拼接
console.log(re) //10*2*3*4*44*90,10*[object Object]
(2) 调用字符串对象的split('分隔符') 方法也可以生成数组。
该方法通过一些常见的分隔符,比如分隔单词的空格,将一个字符串分成几部分,并将每部分作为一个元素保存于一个新建的数组中。
var sentence = "the quick brown fox jumped over the lazy dog"; var words = sentence.split(" "); //传参空格,通过空格将字符串分离成数组[] for (var i = 0; i < words.length; ++i) { console.log("word " + i + ": " + words[i]); }
concat() 和 splice() 方法允许通过已有数组创建新数组。
(1) arr1.concat(arr2,arr2,val1,…) 方法可以合并多个数组,创建一个新数组。
该方法的发起者是一个数组,参数是另一个数组。作为参数的数组,其中的所有元素都被连接到调用concat()方法的数组后面。
concat的参数可以是多类型的
var cisDept = ["Mike", "Clayton", "Terrill", "Danny", "Jennifer"]; var dmpDept = ["Raymond", "Cynthia", "Bryan"]; var itDiv = cisDept.concat(dmpDept); console.log(itDiv); console.log(cisDept); itDiv = dmpDept.concat(cisDept); console.log(itDiv);
方法执行完毕后,原数组不变。
var arr=[10,2,3,4,44] var arr2=["hello","h5"] var arr3=["666"] var arr4=arr.concat(arr2,arr3,100,{name:"karen"})// console.log(arr,arr2,arr3,arr4)
(2) arr.splice(index,length) 方法截取一个数组的子集创建一个新数组。
此方法是pop、push、shift、unshift的结合
方法执行完毕后,原数组改变。
//splice(index,length) ,其中index代表截取的起始索引,length代表 var itDiv = ["Mike","Clayton","Terrill","Raymond","Cynthia","Danny","Jennifer"]; var dmpDept = itDiv.splice(3,3); var cisDept = itDiv; console.log(dmpDept); console.log(cisDept);
var arr=[10,30,40,5,6] var re=arr.splice(2,2,"hello","h5")//从下标2开始删除2个元素 并在这里插入"hello","h5" console.log(re,arr) //(2) [40, 5] (5)[10, 30, 'hello', 'h5', 6]
该小节也可称之为“可变函数”。
JavaScript 拥有一组可变函数,使用它们,可以不必引用数组中的某个元素,就能改变数组内容。
数组元素的增删:
– push():在数组的结尾添加一个或多个元素,返回新数组的长度;
– pop():移除数组最后一个元素,返回移除的元素;
– unshift():在数组的开头添加一个或多个元素,返回新数组的长度;
– shift():删除数组第一个元素,并返回删除的元素;
–这四个函数都是在原始数组上进行修改;
splice() 从数组中间添加、替换 和删除元素,splice(startindex,length,val1,val2,val3……)
(1) 添加:arr1.splice(startIndex,0,arr2),注第二个参数为0:往前边前边添加
var nums = [1,2,3,7,8,9]; var newElements = [4,5,6]; nums.splice(3,0,newElements); console.log(nums); console.log(nums.toString()); (2)arr1.splice(startIndex,length,arr2),注第二个参数为被替换的数组长度
var numbers = [0,1,2,3,4,5,6,7,8,9]; numbers.splice(2,3,“a”,“b”,"c");// //数组不变!原理:从索引2开始删除了3个元素,但也从索引2开始添加了元素2、3、4(3) 使用 splice(startIndex,length) 方法从数组中删除元素
var nums = [1,2,3,100,200,300,400,4,5]; nums.splice(3,4); console.log(nums);
reverse(),将数组中元素的顺序进行翻转。 改变原数组
var arr=[[10,20],90,"hello",{name:"karen"}] var re=arr.reverse() console.log(re,arr,re===arr)
sort(),对字符串进行排序(默认是按照表码排序),字母按顺序排序(大写字母均比小写字母小)。一般用来排姓名 返回新数组
var names =['Ana', 'ana', 'john', 'John']; console.log(names.sort()); //['Ana', 'John', 'ana', 'john'] var nums = [3,1,2,100,4,200]; nums.sort(); console.log(nums); //[1, 100, 2, 200, 3, 4]
面试题: 使用6种方式求出数组中最大的数
1、先用sort进行大到小排序,取数组下标0
2、外面放一个全局变量为最小值,然后依次与数组数字比较,比变量的值大,就替换
sort方法接受compareFunction作为参数,然后sort会用它排序数组,使数组按升序排序。
故要想得到顺序排列的数字数组,需要自定义方法:
var nums = [3,1,2,100,4,200]; function compare(a, b) { if (a < b) { return -1; } if (a > b) { return 1; } // a必须等于b return 0; } nums.sort(compare);
要得到字符串忽略大小写的比较数组,自定义方法:
var names = ['Ana', 'ana', 'john', 'John']; names.sort(function(a, b){ if (a.toLowerCase() < b.toLowerCase()){ return -1 } if (a.toLowerCase() > b.toLowerCase()){ return 1 } return 0; });
var arr=[10,50,40,20,30,6] var re=arr.sort(function(a,b){ return b-a }) console.log(re,arr) //(6) [50, 40, 30, 20, 10, 6] (6) [50, 40, 30, 20, 10, 6]
valueOf()
var arr=[10,80,30,20] console.log(arr.valueOf()) //[10,80,30,20] var arr=[10,20,304] var arr2=new Array(20,30,405,10) console.log(arr2.valueOf()) //(4) [20, 30, 405, 10]
这些方法的参数都是函数,可以对数组中的每一个元素运用该函数,原数组不变。
(1) forEach() :对数组中的每一项运行给定函数,没有返回值,它和使用for循环的结果相同
function square(num) { console.log(num * num); } var nums = [1,2,3,4,5,6,7,8,9,10]; nums.forEach(square); var data=[1,2,3]; data.forEach(function(item,index,array){ console.log(item*item); console.log(array.concat(array)); }) //item 指代元素值,index 指代元素索引,array 指代数组本身,形参位置固定
(2) every():对数组中的每一项运行给定函数,如果该函数对每一个项都返回true,则返回true;
反之,有一个值是false就返回false(默认返回false)。function isEven(num) { return num % 2 == 0; } var nums = [2,3,4,6,8,10]; var even = nums.every(isEven); //every console.log(even);// //也可参照上面匿名函数的例子,给every接收的函数传参(item,index,array)
(3) some():对数组中的每一项运行给定函数,如果该函数对任一一项返回true,则返回true(默认返回false)。
function isEven(num) { return num % 2 == 0; } var nums = [1,3,,,10,]; var someEven = nums.some(isEven); //some console.log(someEven); //也可参照匿名函数的例子,给every函数传参(item,index,array)
(1) map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
function curve(grade) { return grade += 5; } var grades = [77, 65, 81, 92, 83]; var newgrades = grades.map(curve); //map console.log(newgrades); var data=[1,2,3]; var result4=data.map(function(item,index,array){ return item*2; }) console.log(result4);
(2) filter():传入一个返回值为布尔类型的函数。
和every()方法不同的是, 当对数组中的所有元素应用该函数,结果均为 true 时,该方法并不返回true,而是返回一个新数组,该数组包含应用该函数后结果为 true 的元素。
function isEven(num) { return num % 2 == 0; } var nums = []; for (var i = 0; i < 20; ++i) { nums[i] = i+1; } var evens = nums.filter(isEven); //filter console.log(evens);
reduce和reduceRight:使用指定的函数对数组元素进行组合,生成一个值,接收两个参数。
var numbers = [1,2,23,34,5,6,78,98,900]; numbers.reduce(function(previousValue, currentValue, index,array){ return previousValue + currentValue ; },initialValue);
详细解释:
– 参数一:要执行的函数,有返回值,函数内部处理的参数如下
previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
currentValue (数组中当前被处理的元素)
index (当前元素在数组中的索引)
array (调用 reduce 的数组)
– 参数二:传递给函数的默认值,可忽略
– reduce从左向右操作,reduceRight表示从右向左操作
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4) //有点像递归 //看了代码也不一定懂,那我们就多看几个代码
常规用法有哪些?
求累加:
var a = [1,2,23,34,5,6,78,98,900]; var n = a.reduce( function (x, y) { return x + y; } , 0); //参数一匿名函数function,为要执行的函数 //参数二为0,函数的默认起始值,即第一次执行0将被赋值给previousValue;求累积:
var a = [1,2,23,34,5,6,78,98,900]; var m = a.reduce(function (x, y) { return x*y; } ,1)求数组最大值:
var a = [1,2,23,34,5,6,78,98,900]; var max = a.reduce(function (x, y) { return x>y?x:y; });
Array.isArray(arr):判断是否是数组;
var a = [1,2,23,34,5,6,78,98, 23,900]; //数组是特殊的对象类型 console.log(typeof a); //object console.log(Array.isArray(a)); //true console.log(a instanceof Array); //true var b = {x:1, y:2}; console.log(Array.isArray(b)); //false
通过对比数组、对象,我们发现完全可以使用对象来模拟数组,只要我们定义的对象的每个元素的键名都使用数字并且让其保持递增,且动态的定义一个length属性来表示元素个数,那么从效果上来说,基本就个数组相同了!
类数组对象 :只包含使用从零开始,且自然递增的整数做键名,并且定义了length表示元素个数的对象,我们就认为他是类数组对象!
//定义数组和类数组对象 var arr = [1,2,3]; var obj = {0: 1, 1: 2, 2: 3, length: 3}; //元素读写操作 console.log(arr[0], obj[0]) console.log(arr['length'], obj['length']) arr[0] = 9; obj[0] = 9; console.log(arr[0], obj[0]) //遍历 for(var i = 0, len = arr.length; i < len; i++) { //arr[i].... } for(var i = 0, len = obj.length; i < len; i++) { //obj[i].... } //类型判断 console.log(typeof arr); console.log(Array.isArray(arr)); console.log(arr instanceof Array); console.log(typeof obj); console.log(Array.isArray(obj)); console.log(obj instanceof Array);
通过上面我们对于定义的介绍,以及简单的对比,我们不难看出,其实我们可以从数据结构上把js的数组归为对象,因为我们可以使用对象来模拟数组,当然这里仅仅说的是数据结构上,其实他们本身所继承来的方法和一些属性是不同的!在平常的理解中大家可以把数组看成是特殊的对象,以方便理解!
arguments类数组对象:
//类数组 function fn () { console.log(arguments); console.log(typeof arguments); console.log(Array.isArray(arguments)); } fn(1,2,3,4); //依次打印:Arguments(4)、object、false
arguments最重要的用法--函数重载 :
function doAdd() { if(arguments.length == 1) { alert(arguments[0] + 5); } else if(arguments.length == 2) { alert(arguments[0] + arguments[1]); } } doAdd(10); doAdd(40, 20);
JavaScript 只支持一维数组,但是通过在数组里保存数组元素的方式,可以轻松创建多维数组。
二维数组类似一种由行和列构成的数据表格。在 JavaScript 中创建二维数组,需要先创建一个数组,然后让数组的每个元素也是一个数组。
[[],[]]
最起码,我们需要知道二维数组要包含多少行,有了这个信息,就可以创建一个 n 行 1列的二维数组了:
var twod = []; var rows = 5; for (var i = 0; i < rows; ++i) { twod[i] = [5]; } [[1,2,3,4,5]] [[5],[5],[5],[5],[5]]//最外层数组的数据项对应的是行,每一个数据项里有几个元素对应该行就有几列
处理二维数组中的元素,有两种最基本的方式:按列访问和按行访问。
var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]]; var total = 0; var average = 0.0; for (var row = 0; row < grades.length; ++row) { for (var col = 0; col < grades[row].length; ++col) { total += grades[row][col]; } average = total / grades[row].length; console.log("Student " + parseInt(row+1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; }
参差不齐的数组是指数组中每行的元素个数彼此不同。有一行可能包含三个元素,另一行可能包含五个元素,有些行甚至只包含一个元素。
var grades = [[89, 77],[76, 82, 81],[91, 94, 89, 99]]; var total = 0; var average = 0.0; for (var row = 0; row < grades.length; ++row) { for (var col = 0; col < grades[row].length; ++col) { total += grades[row][col]; } average = total / grades[row].length; console.log("Student " + parseInt(row+1) + " average: " + average.toFixed(2)); total = 0; average = 0.0; }