JavaScript数组

数组的创建

JavaScript 中的数组每一项可以保存任何类型的数据,并且,JavaScript 数组的大小时动态调整的。

JavaScript 中允许我们使用两种方式来创建数组:

// 方式一:使用 Array() 构造函数
var names = new Array();
var colors = new Array(5);
var ages = new Array(20, 18, 22);

// 方式二:使用字面量
var options = ['A', 'B', 'C'];

这里推荐第二种创建数组的方式。

注意:

var values = [1, 2,];

在数组字面量的最后一项添加 , 会造成浏览器解析不一致。

在 IE8 及之前版本的浏览器中会创建一个包含3项的数组:[1, 2, undefined] ;而其他浏览器则表现正常。所以,强烈建议不要在数组字面量的最后一项添加 ,

数组的检测

JavaScript 中数组也是对象,通过 typeof 并不能区分数组、对象和 null这里是 MDN 关于 typeof 的返回结果表

intanceof

intanceof 运算符可以用来判断某个构造函数的 prototype 属性所指向的对象是否存在于另外一个要检测对象的原型链上。可以这样使用:

var values = [1, 2, 3];

console.log(values instanceof Array);  // true

Object.prototype.toString

var values = [1, 2, 3];

console.log(Object.prototype.toString.call(values));  // [object Array]

利用原生数组的构造函数名与全局作用域无关,因此可以保证使用 toString() 可以返回一致的值。这里可以封装一个函数:

function isArray(value){
  return Object.prototype.toString.call(value) === '[object Array]';
}

var values = [1, 2, 3];

console.log(isArray(values));  // true

Array.isArray()

ES5 新增了这个方法,用于确定某个值到底是不是数组。

但是,这个方法不兼容 IE8 及以下的浏览器。所以,为了增加兼容性,可以添加下面的代码:

if(!Array.isArray){
  Array.isArray = function(args){
    return Object.prototype.toString.call(args) === '[object Array]';
  };
}

转换方法

join()

join() 方法接收一个用作分隔符的字符串作为参数,然后返回包含所有项的字符串。当不传入参数时,默认使用 , 分隔。

var values = [1, 2, 3];
console.log(values.join());  // '1,2,3'
console.log(values.join(''));  // '123'
console.log(values.join(','));  // '1,2,3'
console.log(values.join(' | '));  // '1 | 2 | 3'

toLocaleString(), toString(), valueOf()

var values = [1, 2, 3];
console.log(values.toLocaleString());
console.log(values.toString());
console.log(values.valueOf());
alert(values.valueOf());

调用 valueOf() 方法还是返回数组本身,而 toLocaleString(), toString(), 方法是返回字符串。

注意:如果是 alert() 函数,由于它接收的是字符串参数,会在后台调用 toString() 方法,所以 alert(values.valueOf()); 返回的也是字符串。

栈和队列方法

push(), pop()

栈是一种先入先出的数据结构。JavaScript 数组中的 push(), pop() 方法就可以模拟这种栈结构。

push() 用于往数组的末尾添加一项,而 pop() 用于删除数组的最后一项。

push() 可以接受任意多数量的参数,并依次将它们添加到数组的最后一项,最后返回数组的长度

而每执行一次 pop() ,都删除数组的最后一项,返回的是被删除的项

执行一次 push() ,数组长度加1;反之,执行一次 pop() 数组长度减1。

var values = [1, 2, 3];

var newArrayLength = values.push(4);
console.log(values, newArrayLength);

var lastItem = values.pop();
console.log(values, lastItem);

console.log(values);

shift(), unshift()

队列是一种先进先出的数据结构。JavaScript 数组中的 shift(), unshift() 方法可以模拟队列结构。

shift() 用于删除数组的第一项,而 unshift() 用于往数组的头部添加一项。

shift() 将删除的第一项返回。

unshift() 则用于向数组的头部依次添加任意多项,返回数组的长度。

执行一次 shift() ,数组长度减1;而执行一次 unshift() ,数组长度加1。

var values = [1, 2, 3];

var newArrayLength = values.unshift(0);
console.log(values, newArrayLength);

var firstItem = values.shift();
console.log(values, firstItem);

console.log(values);

重排序方法

reverse()

reverse() 比较简单,就是用于将数组每一项的顺序反转。比如:

var values = [1, 2, 3];

var rValues = values.reverse();

console.log(rValues); // [3, 2, 1]
console.log(values); // [3, 2, 1]

需要注意的是,第二行输出就说明了 reverse() 会改变原来的数组。

sort()

使用 reverse() 还远远不够,在实际中更多时候需要我们自定义排序规则。而 sort() 就是实现这种想法的方法。

在默认情况下,sort() 会调用数组项的 toString() 方法,按照字符串比较进行升序排列。比如:

var values = [1, 40, 10, 5];

values.sort();

console.log(values);  // [1, 10, 40, 5]

reverse() 方法一样,它也会改变原来的数组。

还好,sort() 允许我们将排序函数作为它的参数传递。那么我们就可以声明一个这样的排序函数:

function sortFun(item1, item2){
  if (item1<item2){
    return -1;
  } else if (item1>item2){
    return 1;
  } else {
    return 0;
  }
}

var values = [1, 40, 10, 5];
values.sort(sortFun);
console.log(values);  // [1, 5, 10, 40]

上面这个比较函数适用于大多数数据类型的升序排列。如果要进行降序排列,则可以这样修改函数:

if (item1<item2){
  return 1;
} else if (item1>item2){
  return -1;
}

而对于数值类型或者其 valueOf() 方法能返回数值类型的对象类型,可以使用下面这个更简单的排序函数:

function sortFun (value1, value2){
  return value1 - value2;  // 升序
  /*
  return value2 - value1;  // 降序
  */
}

操作方法

concat()

concat() 可以基于当前数组中的所有项创建一个新数组,并返回新构建的数组。

通过下面这个例子来说明,使用 concat() 不会改变原数组。

var values = [1, 2, 3];

var newValues = values.concat();

newValues.pop();

console.log(newValues);  // [1, 2]
console.log(values);  // [1, 2, 3]

通常,可以使用 concat() 将额外的数据合并进数组:

var values = [1, 2, 3];
var newValues = values.concat(4, [5, 6]);

console.log(newValues);  // [1, 2, 3, 4, 5, 6]

slice()

slice() 则是基于当前数组截取满足条件的元素作为新数组返回。

一般来说,slice() 接收两个参数 - 起始位置和结束位置。范围是 [startIndex, endIndex)

当只有1个参数传递给 slice() 时,则截取范围为 [startIndex, arr.length-1]

来看下面的例子:

var values = [1, 2, 3, 4, 5, 6, 7];

var values2 = values.slice(2);
var values3 = values.slice(2, 5);

console.log(values2);  // [3, 4, 5, 6, 7]
console.log(values3);  // [3, 4, 5]

还需要注意的两点是:

  • 如果 slice() 方法的参数中有负数,则用数组的长度加上该数来确定响应的位置。比如:数组长度为5,则 slice(-2, -1)slice(3, 4) 的结果一致。
  • 如果结束位置小于起始位置,则返回空数组。

splice()

splice() 算是最强大的数组方法了,它可以删除、插入、替换数组的项。

splice() 接收2个参数时,表示要删除的第一项的位置和要删除的项数。

splice() 接收3个参数(甚至更多)时,表示要插入项的起始位置、0(要删除的项数)和要插入的项。

替换数组项,则只需要让 splice() 的第2个参数不为0即可。

注意: splice() 始终返回从原数组中删除的数组项,如果没有删除项,则返回空数组。

var values = [1, 2, 3, 4, 5, 6, 7];

var remove = values.splice(2, 1);

console.log(values);  // [1, 2, 4, 5, 6, 7]
console.log(remove);  // [3]

remove = values.splice(4, 0, 8, 9);
console.log(values);  // [1, 2, 4, 5, 8, 9, 6, 7]
console.log(remove);  // []

remove = values.splice(3, 2, 10, 11);
console.log(values);  // [1, 2, 4, 10, 11, 9, 6, 7]
console.log(remove);  // [5, 8]

位置方法

indexOf(), lastIndexOf()

这两个方法都可以接收两个参数,第一个参数表示要查找的项;第二个参数为可选的,表示查找的起点位置。区别在于 indexOf() 从数组的头部开始查找,lastIndexOf() 从数组的末尾开始查找。

它们都返回要查找的项(第一次出现)的位置,如果没有找到则返回 -1。另外,查找过程中进行比较时是使用全等(===)进行比较。

var values = [1, 2, 3, 2, 1];

console.log(values.indexOf(2));  // 1
console.log(values.lastIndexOf(2));  // 3
console.log(values.indexOf(2, 2));  // 3
console.log(values.lastIndexOf(2, 2));  // 1
console.log(values.indexOf(4));  // -1

迭代方法

在 ES5 中,数组拥有5个迭代方法。

每个方法都接收两个参数:一个作用于每一项的迭代函数 iteratee,和(可选的)运行该函数的作用域对象 [context]

迭代函数 iteratee 会接受三个参数:数组的每一项 item ,每一项的位置 index ,和数组对象 array 。注意只有 item 参数是必须的。

every()

如果数组的每一项都能被 iteratee 函数返回 true ,则返回 true

var values = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = values.every(function(item){
  return item > 2;
});

console.log(result);  // false

some()

遍历整个数组,只要有一个项满足 iteratee 函数的条件,则返回 true

var values = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = values.some(function(item){
  return item > 2;
});

console.log(result);  // true

filter()

遍历整个数组,返回满足 iteratee 函数条件的数组项组成的数组。

var values = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = values.filter(function(item){
  return item > 2;
});

console.log(result);  // [3, 4, 5, 4, 3]

forEach()

遍历整个数组,对每一个数组项运行 iteratee 函数。它没有返回值。

var values = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = values.forEach(function(item){
  item * 2;
});

console.log(result);  // undefined
console.log(values);  // [1, 2, 3, 4, 5, 4, 3, 2, 1]

注意:它也不能改变原数组。可以看看 map() 方法。

即使显式写成 return 语句,也不会有返回值!

map()

遍历整个数组,返回 iteratee 函数每次调用后的结果组成的数组。

var values = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var result = values.map(function(item){
  return item * 2;
});

console.log(result);  // [2, 4, 6, 8, 10, 8, 6, 4, 2]
console.log(values);  // [1, 2, 3, 4, 5, 4, 3, 2, 1]

如果这里省去 return 关键字,那么 result 将会是 [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]

注意:这里的 return 只是 iteratee 函数的返回,并不是这些迭代方法的返回!

归并方法

reduce(), reduceRight()

ES5 还新增了两个归并方法。这两个方法会遍历整个数组,然后根据 iteratee 函数构建一个最终值并返回。它们都接收2个参数:一个作用于每一项的迭代函数 iteratee 和可选的作为归并的基础值 memo

而这个 iteratee 函数可接收4个参数:前一个值 prev, 当前值 cur, 项的索引 index 和数组对象 array 。这个函数的返回值都会作为第一个参数自动传递给下一项。

var values = [1, 2, 3];
var sum = values.reduce(function(prev, cur){
  return prev + cur;
});

console.log(sum);  // 6
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值