数组的标准定义:一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量。
JavaScript 中的数组是一种特殊的对象,用来表示偏移量的索引是该对象的属性,索引可能是属性。然而,这些数字索引在内部被转换为字符串类型,这是因为JS对象中的属性名必须是字符串;即数组在JS中只是特殊的对象。
1)创建数组:
① 通过[]
操作符声明数组变量:var arr = [];
② 通过[]
操作符声明数组变量,同时在[]
操作符内放入一组元素:var arr = [1,2,3,4];
③ 通过调用Array的构造函数创建数组:var arr = new Array();
④ 通过调用Array的构造函数创建数组,同时在构造函数中传入一组元素作为数组的初始值:var arr = new Array(1,2,3,4);
⑤ 通过调用Array的构造函数创建数组,同时可以只传入一个参数,来指定数组的长度:var arr = new Array(10);
在脚本语言中,常见的特性——数组中的元素不必是同一种数据类型;
Array.isArray(arrArg);
- 用来判断一个对象是否是数组,若是返回true,否则返回false;
2)读写数组:
可以通过[]
操作符读写数组中的元素;
3)由字符串生成数组:
调用字符串的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]);
}
/*
输出:
word 0 : the
word 1 : quick
word 2 : brown
word 3 : fox
word 4 : jumped
word 5 : over
word 6 : the
word 7 : lazy
word 8 : dog
*/
4)对数组的整体性操作:
数组浅复制: 修改任意一个都会对另一个造成同样的影响;
var nums = [1, 2, 3, 4, 5, 6, 7];
var newNum = nums;
newNum.push(8);
console.log('nums : ' + nums);
console.log('newNum : ' + newNum);
/*
输出:
nums : 1,2,3,4,5,6,7,8
newNum : 1,2,3,4,5,6,7,8
*/
数组深复制:将原数组中的每一个元素都复制一份到新数组中。
function deepCopy(arr) {
var newObj;
Object.prototype.toString.call(arr) === '[object Array]'? newObj = []:newObj = {};
for(var key in arr){
newObj[key] = (typeof arr[key] === 'object'?deepCopy(arr[key]):arr[key]);
}
return newObj;
}
1)查找元素:
indexOf()
方法:(从左向右查找)用来查找传进来的参数在目标数组中是否存在,如果目标数组包含该参数,就返回该元素在数组中的索引,如果不包含,就返回-1;
lastIndexOf()
方法:(从右向左查找)用来查找传进来的参数在目标数组中是否存在,如果目标数组包含该参数,就返回该元素在数组中的索引,如果不包含,就返回-1;
2)数组的字符串表示:
join()
方法:将数组转换为字符串;
toString()
方法:将数组转换为字符串;
3)由已有数组创建新数组:
concat()
方法:允许通过已有数组创建新数组,可以合并多个数组创建一个新数组;
splice()
方法:允许通过已有数组创建新数组,截取一个数组的子集创建一个新数组;
1)为数组添加元素:
push()
方法:会将一个元素添加到数组末尾,可以一次添加多个元素;
也可以使用
length
属性为数组添加元素,如:num[num.length] = 5;
unshift()
方法:可以将元素添加到数组的开头,可以一次添加多个元素;
2)从数组中删除元素:
pop()
方法:可以删除数组末尾的元素;
shift()
方法:可以删除数组的第一个元素;
3)从数组中间位置添加或删除元素
splice()
方法:为数组添加元素,参数如下:
4)为数组排序
reverse()
方法:将数组中的元素的顺序进行翻转(注意:该方法会修改原数组);
sort()
方法:对数组进行排序,默认情况下 ,sort
方法按字典顺序对元素进行排序,即使元素为数字类型也会被认为是字符串类型(注意:该方法会修改原数组);
var arr3 = [1,5,2,4,10,8,7];
arr3.sort(function (a,b) {
return a-b;
});
console.log(arr3); // [ 1, 2, 4, 5, 7, 8, 10 ]
1)不生成新数组的迭代器方法:
forEach()
方法:该方法接受一个函数作为参数,对数组中的每个元素使用该函数;
var nums = [1,2,3,4,5,6,7,8];
nums.forEach(function (num) {
console.log(num,num*num);
});
every()
方法:该方法接受一个返回值为布尔类型的函数,对数组的每个元素使用该方法,如果对于所有元素,该函数均返回true
,则该方法返回true
;
var arr1 = [1,2,3,4,5,6];
var arr2 = [2,4,6,8,10];
function isEven(num) {
return num%2;
}
console.log(arr1.every(isEven));
console.log(arr2.every(isEven));
some()
方法:该方法接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回true
,该方法就返回true
;
reduce()
方法:(从左向右)接受一个函数,返回一个值;该方法会从一个累加值开始,不断对累加值和数组中的后续元素调用该函数,直到数组中的最后一格元素,最后返回得到的累加值(注意:也可以用来将数组中的元素连接成一个长的字符串);
var sum = arr1.reduce(function (a,b) {
return a+b;
});
console.log(sum);
reduceRight()
方法:(从右向左)接受一个函数,返回一个值;该方法会从一个累加值开始,不断对累加值和数组中的后续元素调用该函数,直到数组中的最后一格元素,最后返回得到的累加值(注意:也可以用来将数组中的元素连接成一个长的字符串);
2)生成新数组的迭代器方法:
map()
方法:对数组中的每个元素使用某个函数,并返回一个新的数组,该数组的元素是对原有元素应用某个函数的结果;
var arr3 = [22,45,11,57,38];
function addNum(num) {
return num += 10;
}
var res = arr3.map(addNum);
console.log(res);
filter()
方法:传入一个返回值为布尔类型的函数,当所有元素应用该函数时,返回一个新数组,该数组包含应用该函数后结果为true的元素;
var nums2 = [12, 14, 23, 4, 6];
function isOdd(num) {
return !(num % 2);
}
console.log(nums2.filter(isOdd)); // [ 12, 14, 4, 6 ]
filter
方法的其他应用——筛选数组元素:
var grades = [39,43,89,19,46,54,5,13,31,27,96,64,63,30,78,89,68,40];
function isPass(grade) {
return (grade >=60);
}
var passGrade = grades.filter(isPass);
console.log('All grades : ');
console.log(grades);
console.log('Passing grades : ');
console.log(passGrade);
/*
输出:
All grades :
[ 39, 43, 89, 19, 46, 54, 5, 13, 31, 27, 96, 64, 63, 30, 78, 89, 68, 40 ]
Passing grades :
[ 89, 96, 64, 63, 78, 89, 68 ]
*/
JavaScript中只支持一维数组,但是通过在数组中保存数组元素的方式,可以轻松创建多维数组;
1)创建二维数组:
// JavaScript:The Good Parts
Array.matrix = function (numrows, numcols, initial) {
var arr = [];
for (var i = 0; i < numrows; i++) {
var columns = [];
for (var j = 0; j < numcols; j++) {
columns[j] = initial;
}
arr[i] = columns;
}
return arr;
};
var nums = Array.matrix(3,2,'1');
console.log(nums);
2)处理二维数组的元素:
处理二维数组,有两种最基本的方式:按列访问,按行访问;
// 每个学生三科成绩,求平均分:
var grades = [[89, 77, 68], [79, 60, 90], [70, 88, 60]];
for (var i = 0; i < grades.length; i++) {
var total = 0;
var average = 0;
for (var j = 0; j < grades[i].length; j++) {
total += grades[i][j];
}
average = total / grades[i].length;
console.log('Student ' + i + ' average : ' + average.toFixed(2));
}
// 计算各科的平均成绩
for (var m = 0; m < grades.length; m++) {
var total = 0;
var average = 0;
for (var n = 0; n < grades[m].length; n++) {
total += grades[n][m];
}
average = total / grades.length;
console.log('Test ' + (m+1) + ' average : ' + average.toFixed(2));
}
数组的方法、属性对对象依然适用。
1、创建一个记录学生成绩的对象,提供一个添加成绩的方法,以及一个现实学生平均成绩的方法:
function StuGrade() {
this.dataStore = [];
this.addGrade = addGrade;
this.showAverage = showAverage;
}
function addGrade(grade) {
this.dataStore.push(grade);
}
function showAverage() {
var total = 0;
for(var i = 0;i
2、将一组单词存储在一个数组中,并按正序和倒叙分别显示这些单词:
使用
sort
、reverse
方法即可实现;
3、创建一个对象,用于保存观测到的周最高温度,该对象有多个方法:①增加一条新的气温记录;②计算存储在对象中的平均气温;(扩展:修改创建的对象,使它可以使用一个二维数组来存储每个月的有用数据,增加一些方法用以显示月平均数,具体某一周平均数和所有周的平均数)
function Temperature() {
this.num = 0;
this.dataStore = [];
this.add = function (t) {
var n = this.num % 7;
var m = parseInt(this.num / 7);
if (n == 0) {
this.dataStore.push([]);
}
this.dataStore[m].push(t);
this.num++;
};
this.weekAverage = function (w) {
var total = 0;
w = w-1;
for (var i = 0; i < this.dataStore[w].length; i++) {
total += this.dataStore[w][i];
}
return total / this.dataStore[w].length;
};
this.monthAverage = function () {
var t = 0;
for(var k =0 ;k
4、创建一个对象,它将字母存储在一个数组中,并且用一个方法可以将字母连在一起,显示成一个单词;
function ConstWord() {
this.data = [];
this.add = function (c) {
this.data.push(c);
};
this.connect = function () {
return this.data.join('');
};
}
var w = new ConstWord();
w.add('H');
w.add('e');
w.add('l');
w.add('l');
w.add('o');
console.log(w.connect());
1、数组去重:
/*
* 方法一:
* 使用indexOf方法去重
* 优点:可以识别字符串类型的数字和数字类型的数字;
* 缺点:对于引用类型的数组元素无法判断
* */
function unique1(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) == -1) {
res.push(arr[i]);
}
}
return res;
}
var arr1 = [1, 2, 1, 6, 3, 7, 2, 4, 9, 5];
console.log(unique1(arr1)); // [ 1, 2, 6, 3, 7, 4, 9, 5 ]
var arr2 = [1, 2, '1', 6, 3];
console.log(unique1(arr2)); // [ 1, 2, '1', 6, 3 ]
var arr3 = [1, 2, '1', 6, 3, [1, 2, 4, 6], [1, 2, 4, 6], 7, 2, 4, 9, 5];
console.log(unique1(arr3)); // [ 1, 2, '1', 6, 3, [ 1, 2, 4, 6 ], [ 1, 2, 4, 6 ], 7, 4, 9, 5 ]
console.log('===============================');
/*
* 方法二:
* 利用hash表
* 优点:对引用类型的数组元素可以判断去重
* 缺点:对数字类型的字符串无法判断
*(原因:对象类型的属性名均被转换为字符串类型,不论原本是什么类型)
* */
function unique2(arr) {
var hash = {};
var res = [];
for (var i = 0; i < arr.length; i++) {
if (!hash[arr[i]]) {
hash[arr[i]] = true;
res.push(arr[i]);
}
}
return res;
}
var arr2_1 = [1, 2, 1, 6, 3, 7, 2, 4, 9, 5];
console.log(unique2(arr2_1)); // [ 1, 2, 6, 3, 7, 4, 9, 5 ]
var arr2_2 = [1, 2, '1', 6, 3];
console.log(unique2(arr2_2)); // [ 1, 2, 6, 3 ]
var arr2_3 = [1, 2, '1', 6, 3, [1, 2, 4, 6], [1, 2, 4, 6], 7, 2, 4, 9, 5];
console.log(unique2(arr2_3)); // [ 1, 2, 6, 3, [ 1, 2, 4, 6 ], 7, 4, 9, 5 ]
console.log('================================');
/*
* 方法三:
* 双重遍历
* 优点:可以识别出字符串类型的数字;
* 缺点:对引用类型的数组元素无效,且效率略低;
* */
function unique3(arr) {
if (arr.length == 0 || arr.length == 1)
return;
var res = [arr[0]], isRepeat;
for (var i = 0; i < arr.length; i++) {
isRepeat = false;
for (var j = 0; j < res.length; j++) {
if(res[i] === arr[j]){
isRepeat = true;
break;
}
}
if(!isRepeat){
res.push(arr[i]);
}
}
return res;
}
var arr3_1 = [1, 2, 1, 6, 3, 7, 2, 4, 9, 5];
console.log(unique3(arr3_1)); // [ 1, 2, 6, 3, 7, 4, 9, 5 ]
var arr3_2 = [1, 2, '1', 6, 3];
console.log(unique3(arr3_2)); // [ 1, 2, '1', 6, 3 ]
var arr3_3 = [1, 2, '1', 6, 3, [1, 2, 4, 6], [1, 2, 4, 6], 7, 2, 4, 9, 5];
console.log(unique3(arr3_3)); // [ 1, 2, '1', 6, 3, [ 1, 2, 4, 6 ], [ 1, 2, 4, 6 ], 7, 2, 4, 9, 5 ]
2、数组乱序:
// 方法一:
// 使用random方法获取随即元素添加到res中
// 同时使用delete删除array中对应的元素
function shuffle1(array) {
var res = [];
var i = 0;
var n = array.length;
while(n){
i = Math.floor(Math.random()*array.length);
if(i in array){
res.push(array[i]);
delete array[i];
n--;
}
}
return res;
}
var nums = [1,2,3,4,5,6];
console.log(shuffle1(nums));
// 方法二:
// 与方法一类似,只是是使用splice方法移除array中的元素
function shuffle2(array) {
var res = [];
var n = array.length;
var i = 0;
while (n) {
i = Math.floor(Math.random() * array.length);
if (i in array) {
res.push(array.splice(i, 1)[0]);
n--;
}
}
return res;
}
var nums2 = [1, 2, 3, 4, 5, 6];
console.log(shuffle2(nums2));
// 方法三:
// 前面随机抽取一个数值与末尾的元素交换,后面依次类推;
function shuffle3(array) {
var n = array.length;
var i = 0;
while(n){
i = Math.floor(Math.random()*n--);
t = array[n];
array[n] = array[i];
array[i] = t;
}
return array;
}
var nums3 = [1, 2, 3, 4, 5, 6];
console.log(shuffle3(nums3));
3、数组求交集:
Array.prototype.intersection = function (arr) {
return this.filter(function (n) {
return arr.indexOf(n) != -1;
})
};
var arr1 = [1,4,2,6,9,5];
var arr2 = [1,5,2,5,0,3];
var res = arr1.intersection(arr2);
console.log(res); // [ 1 , 2 , 5 ]
4、数组求并集:
// 思路一:将两个数组连接在一起再去重
Array.prototype.unionSet = function (arr) {
var res = this.concat(arr);
return unique(res);
};
function unique(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) == -1) {
res.push(arr[i]);
}
}
return res;
}
var arr1 = [1, 4, 2, 6, 9, 5, 1];
var arr2 = [1, 5, 2, 5, 0, 3];
var res = arr1.unionSet(arr2);
console.log(res);
// 思路二:求两个数组的交集、两个数组的差集(A-B及B-A),再将三个数组连接在一起
5、数组求差集:
Array.prototype.differenceSet = function (arr) {
return this.filter(function (n) {
return arr.indexOf(n) == -1;
})
};
var arr1 = [1, 4, 2, 6, 9, 5, 1];
var arr2 = [1, 5, 2, 5, 0, 3];
var one_two = arr1.differenceSet(arr2);
var two_one = arr2.differenceSet(arr1);
console.log('arr1-arr2: '+one_two);
console.log('arr2-arr1: '+two_one);
6、数组判断:
// 方法一:自带的isArray方法
var nums = [1,2,3];
console.log(Array.isArray(nums)); // true
// 方法二:利用instanceof 运算符判断
var arr = ['2','1','5'];
console.log(arr instanceof Array); // true
// 方法三:利用toString判断
var str = ['h','e','l','l','o'];
console.log(Object.prototype.toString.call(str) == '[object Array]'); // true
Math 对象:保存数学公式和信息提供了一个公共位置;
1)Math 对象的属性:
Math.E
- 自然对数的底数,即常量e的值;Math.LN10
- 10的自然对数;Marh.LN2
- 2的自然对数;Marh.LOG2E
- 以2为底e的对数;Marh.LOG10E
- 以10为底e的对数;Marh.PI
- π的值;Marh.SQRT1_2
- 1/2的平方根,即2的平方根的倒数;Marh.SQRT2
- 2的平方根;2)min()和max()方法:
这两个方法都可以接收任意多个数值参数;
min()
方法:确定一组数值中的最小值;
max()
方法:确定一组数值中的最大值;
// 要找到数组中的最大或最小值:
var nums = [1,2,3,2,7,5,9];
var max = Math.max.apply(Math,nums); // 9
var min = Math.min.apply(Math,nums); // 1
3)舍入方法:
Math.ceil()
方法:执行向上舍入;Math.floor()
方法:执行向下舍入;Math.round()
方法:执行标准舍入(即四舍五入);4)random()方法:
Math.random()
方法:返回大于等于0小于1的随机数,即[0,1);
从某个整数范围内随即选择一个值:
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)
// 返回指定范围内的一个随即数
function selectFrom(lowerValue , upperValue){
var choice = upperValue - lowerValue;
return Math.floor(Math.random() * choice + lowerValue);
}
5)其他方法:
Math.abs(num)
方法:返回num的绝对值Math.exp(num)
方法:返回Math.E的num次幂Math.log(num)
方法:返回num的自然对数Math.pow(num, power)
方法:返回num的power次幂Math.sqrt(num)
方法:返回num的平方根Math.acos(x)
方法:返回x的反余弦值Math.asin(x)
方法:返回x的反正弦值Math.atan(x)
方法:返回x的反正切值Math.atan2(y, x)
方法:返回y/x的反正切值Math.cos(x)
方法:返回x的余弦值Math.sin(x)
方法:返回x的正弦值Math.tan(x)
方法:返回x的正切值delete 只有当一个属性无法被删除时才返回 false,若删除成功则返回true;