JS基础--Array
数组
JavaScript中对数组的定义
数组的标准定义是:一个存储元素的线性集合(collection),元素可以通过索引来任意存 取,索引通常是数字,用来计算元素之间存储位置的偏移量。
创建数组的几种方法
- var numbers = [];
- var numbers = [1,2 ,3];
- var numbers = new Array(); //调用 Array 的构造函数创建数组
- var numbers = new Array(1, 2 , 3); //[1, 2, 3]
- var numbers = new Array(3); //[undefined, undefined, undefined]
用Array 的构造函数创建数组时,不传入参数是创建一个空数组,传入一组元素时是为这个数组设置了初始值,传入一个参数时是指定创建的这个数组的长度。
判断是否是一个数组
Array.isArray() 来判断一个对象是否是数组
延伸知识点—-类型检测
JavaScript有四种方法,可以确定一个值到底是什么类型。
- typeof运算符 —-返回的都是字符串
- ‘number’
- ‘string’
- ‘boolean’
- ‘undefined’
- ‘object’
- ‘function’
-
instanceof运算符 —-表示指定对象是否为某个构造函数的实例
instanceof只能用来判断对象和函数,不能用来判断字符串和数字等
instanceof运算符的左边是实例对象,右边是构造函数。它会检查右边构建函数的原型对象,是否在左边对象的原型链上。因此,下面两种写法是等价的。
var v = new Vehicle(); v instanceof Vehicle // true v instanceof Vehicle // 等同于 Vehicle.prototype.isPrototypeOf(v)
eg: v instanceof Function v instanceof Object v instanceof Array v instanceof Date ......
-
constructor
每一个对象实例都可以通过 constrcutor 对象访问它的构造函数
但是constructor是不可靠的,在继承的时候会出现问题,看代码
function A () {} function B () {} A.prototype = new B(); //A继承B var aObj = new A(); AObj.constructor === B // true AObj.constructor === A // false 而instanceof方法不会出现该问题,对象直接继承和间接继承的都会报true: aObj instanceof A // true aObj instanceof B // true
解决construtor的问题通常是让对象的constructor手动指向自己
-
Object.prototype.toString方法 —-用来判断一个对象是否是另一个对象的原型
通用但很管繁锁的方法
Object.prototype.toString.call(a) === '[object String]'; Object.prototype.toString.call(b) === '[object Number]'; Object.prototype.toString.call(c) === '[object Array]'; Object.prototype.toString.call(d) === '[object Date]'; Object.prototype.toString.call(e) === '[object Function]';
一个检测数据类型的对象:
var valide = (function(){
// 是否是字符串
function isString(value){
return Object.prototype.toString.call(value) == "[object String]";
}
// 是否是数字
function isNumber(value){
return Object.prototype.toString.call(value) == "[object Number]";
}
// 是否是布尔值
function isBoolean(value){
return Object.prototype.toString.call(value) == "[object Boolean]";
}
// 是否undefined
function isUndefined(value){
return Object.prototype.toString.call(value) == "[object Undefined]";
}
// 是否是null
function isNull(value){
return Object.prototype.toString.call(value) == "[object Null]";
}
// 是否数组
function isArray(value){
return Object.prototype.toString.call(value) == "[object Array]";
}
// 是否是函数
function isFunction(value){
return Object.prototype.toString.call(value) == "[object Function]";
}
// 是否是对象
function isObject(value){
return Object.prototype.toString.call(value) == "[object Object]";
}
// 是否是正则表达式
function isRegExp(value){
return Object.prototype.toString.call(value) == "[object RegExp]";
}
// 是否是日期对象
function isDate(value){
return Object.prototype.toString.call(value) == "[object Date]";
}
return {
isString: isString,
isNumber: isNumber,
isBoolean: isBoolean,
isUndefined: isUndefined,
isNull: isNull,
isArray: isArray,
isFunction: isFunction,
isObject: isObject,
isRegExp: isRegExp,
isDate: isDate
};
})();
valide.isArray([]) //true
字符串转数组
- split()
数组的浅拷贝
var nums = [];
for (var i = 0; i < 10; ++i) {
nums[i] = i+1;
}
var samenums = nums;
nums[0] = 400;
console.log(samenums[0]) // 显示 400
当把一个数组赋给另外一个数组时,只是为被赋值的数组增加了一个新的引用。当 你通过原引用修改了数组的值,另外一个引用也会感知到这个变化。这种行为被称为浅复制,新数组依然指向原来的数组。
数组的深拷贝
function copy(arr1, arr2) {
for (var i = 0; i < arr1.length; ++i) {
arr2[i] = arr1[i];
}
}
var nums = [];
for (var i = 0; i < 10; ++i) {
nums[i] = i+1;
}
var samenums = [];
copy(nums, samenums);
nums[0] = 400;
console.log(samenums[0]) // 显示 1
存取函数
-
indexOf()
如果目标数组包含该参数,就返回该元素在数组中的索引;如果不包含,就返回 -1,如果在数组中有多个重复的值 ,indexOf只会返回重复的第一个值的索引。
-
lastIndexOf()
返回相同元素中最后一个元素的索引,如果没找到相同元素,则返回 -1
数组转字符串
- join()
- toString()
由已有数组创建新数组
- concat 合并多个数组生成一个新的数组
- splice 截取一个数组的子集创建一个新数组
为数组添加元素
- push
- unshift
也可以使用数组的 length 属性为数组添加元素,但 push() 方法看起来更直观
var nums = [1,2,3,4,5];
nums[nums.length] = 6;
console.log(nums); // 1,2,3,4,5,6
和在数组的末尾添加元素比起来,在数组的开头添加元素更难。如果不利用数组提供的可 变函数,则新的元素添加进来后,需要把后面的每个元素都相应地向后移一个位置。下面的代码展示了这一过程:
var nums = [1,2,3,4,5];
for(var i = nums.length; i >= 0; --i) {
nums[i] = nums[i-1]
}
console.log(nums) //(6) [undefined, 1, 2, 3, 4, 5]
nums[0] = 1;
console.log(nums) //(6) [1, 1, 2, 3, 4, 5]
随着数组中存储的元素越来越多,上述代码将会变得越来越低效。
从数组中删除元素
- pop
- shift
用一代码实现shift()方法
var nums = [1,2,3,4,5];
for (var i = 0; i < nums.length; i++) {
nums[i] = nums[i +1];
}
nums.length = nums.length - 1;
console.log(nums); // (5) [2, 3, 4, 5]
从数组中间位置添加和删除元素
- splice
为数组排序
- reverse() //反转数组
- sort()
- 如果元素是字符串类型,那么数组的可变方法 sort() 就非常好使:
- 如果数组元素是数字类型,sort() 需要传一个比较函数
function compare(num1, num2) {
return num1 - num2;
}
var nums = [3,1,2,100,4,200];
nums.sort(compare);
console.log(nums); // 1,2,3,4,100,200
迭代器方法
不生成新数组的迭代器方法
-
forEach
它们要么对于数组中的每个元素执行某种操作,要么返回一个值
该方法接受一个函数作为参数,对数组中的每个元素 使用该函数。
function square(num) {
document.write(num, num * num);
}
var nums = [1,2,3,4,5,6,7,8,9,10];
nums.forEach(square);
-
every()
该方法接受一个返回值为布尔类型的函数,对数组中的每 个元素使用该函数。如果对于所有的元素,该函数均返回 true,则该方法返回 true。
-
some()
该方法接受一个返回值为布尔类型的函数,只要有一个元素使得该函数返回 true,该方法就返回 true。
-
reduce()
reduce() 方法接受一个函数,返回一个值。该方法会从一个累加值开始,不断对累加值和 数组中的后续元素调用该函数,直到数组中的最后一个元素,最后返回得到的累加值。
function add(num1, num2) {
return num1 + num2;
}
var nums = [1,2,3,4,5,6,7,8,9,10];
var sum = nums.reduce(add);
console.log(sum) // 55
reduce() 方法和 add() 函数一起,从左到右,依次对数组中的元素求和,其执行过程如下 所示:
add(1,2) -> 3
add(3,3) -> 6
add(6,4) -> 10
add(10,5) -> 15
add(15,6) -> 21
add(21,7) -> 28
add(28,8) -> 36
add(36,9) -> 45
add(45,10) -> 55
-
reduceRight()
和 reduce() 方法不同,它是从右到左执行, reduceRight() 方法可以将数组中的元素进行翻转。
生成新数组的迭代器方法
- map()
map() 和 forEach() 有点儿像,对数组中的每个元素使用某个函数。两者的区别是 map() 返回一个新的数组,新数组的元素是对原有元素应用某个函数得到的结果。
- filter()
filter() 和 every() 类似,传入一个返回值为布尔类型的函数。
和 every() 方法不同的是, 当对数组中的所有元素应用该函数,结果均为 true 时,该方法并不返回 true,而是返回 一个新数组,该数组包含应用该函数后结果为 true 的元素。
二维和多维数组
创建二维数组
二维数组类似一种由行和列构成的数据表格。在 JavaScript 中创建二维数组,需要先创建 一个数组,然后让数组的每个元素也是一个数组。
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 names = Array.matrix(3,4,0);
console.log(names);
//输出结果:
(3) [Array(4), Array(4), Array(4)]
0:(4) [0, 0, 0, 0]
1:(4) [0, 0, 0, 0]
2:(4) [0, 0, 0, 0]
这种循环同理做一个九九乘法表:
document.write('<table>');
for (var i = 1; i < 10; i++) {
document.write('<tr>');
for (var j = 1; j <= i; j++) {
document.write('<td>' + i + '*' + j + '=' + (i * j) + '</td>');
}
document.write('</tr>');
}
document.write('</table>');
结果如下图:
处理二维数组的元素
有两种最基本的方式
- 按行访问
var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]];
for (var row = 0; row < grades.length; row++) {
var num = 0;
var average = 0;
for (var col = 0; col < grades[row].length; col++) {
num = num + grades[row][col];
}
average = num / grades[row].length;
document.write("Student " + parseInt(row+1) + " average: " +
average.toFixed(2));
}
Student 1 average: 81.33
Student 2 average: 79.67
Student 3 average: 91.33
- 按列访问
var grades = [[89, 77, 78],[76, 82, 81],[91, 94, 89]];
for (var col = 0; col < grades.length; col++) {
var num = 0;
var average = 0;
for (var row = 0; row < grades[col].length; row++) {
num = num + grades[row][col];
}
average = num / grades[col].length;
document.write("Student " + parseInt(col+1) + " average: " + average.toFixed(2));
}
Student 1 average: 85.33
Student 2 average: 84.33
Student 3 average: 82.67
参差不齐的数组–同按行访问
var grades = [[89, 77],[76, 82, 81],[91, 94, 89, 99]];
for (var row = 0; row < grades.length; ++row) {
var total = 0;
var average = 0.0;
for (var col = 0; col < grades[row].length; ++col) {
total += grades[row][col];
}
average = total / grades[row].length;
document.write("Student " + parseInt(row+1) + " average: " + average.toFixed(2));
}
对象数组
function Point(x,y) {
this.x = x;
this.y = y;
}
function displayPts(arr) {
for (var i = 0; i < arr.length; ++i) {
print(arr[i].x + ", " + arr[i].y);
}
}
var p1 = new Point(1,2);
var p2 = new Point(3,5);
var p3 = new Point(2,8);
var p4 = new Point(4,4);
var points = [p1,p2,p3,p4];
for (var i = 0; i < points.length; ++i) {
print("Point " + parseInt(i+1) + ": " + points[i].x + ", " + points[i].y);
}
var p5 = new Point(12,-3);
points.push(p5);
print("After push: ");
displayPts(points);
points.shift();
print("After shift: ");
displayPts(points);
Point 1: 1, 2 Point 2: 3, 5 Point 3: 2, 8 Point 4: 4, 4 After push: 1,2
3,5
2,8
4,4
12, -3
After shift: 3,5
2,8
4,4
12, -3
对象中的数组
function weekTemps() {
this.dataStore = [];
this.add = add;
this.average = average;
}
function add(temp) {
this.dataStore.push(temp);
}
function average() {
var total = 0;
for (var i = 0; i < this.dataStore.length; ++i) {
total += this.dataStore[i];
}
return total / this.dataStore.length;
}
var thisWeek = new weekTemps(); thisWeek.add(52);
thisWeek.add(55);
thisWeek.add(61);
thisWeek.add(65);
thisWeek.add(55);
thisWeek.add(50);
thisWeek.add(52);
thisWeek.add(49);
document.write(thisWeek.average()); // 显示 54.875