Javascript数组方法(译)
在JavaScript中,数组可以使用Array构造函数来创建,或使用[]快速创建,这也是首选的方法。数组是继承自Object的原型,并且他对typeof没有特殊的返回值,他只返回'object'。
运行[] instanceof Array他会返回ture。虽然结果是这样,但也有复杂的类数组对象,如字符串或arguments对象,但arguments对象并非是Array的实例,但他却拥有length属性,而且他的值是可以被索引的,因此他可以像一个数组那样被遍历。
这本文中,我将介绍数组原型的一些方法,并探讨每一种方法的用途:
使用.forEach 来做遍历
使用.some and .every 来断言
使用 .join and .concat 来合并
使用 .pop, .push, .shift, and .unshift 来操作栈和队列
使用 .map 映射模型
使用 .filter 来做查询
使用 .sort 来做排序
使用 .reduce, .reduceRight 来计算
使用 .slice 来复制
.splice 的用途
使用 .indexOf 来查找
in 操作符介绍
.reverse 的用途
使用 .forEach来遍历
======
这是原生Javascript数组最简单的方法之一,但他不支持IE6~8。
forEach 会在遍历数组中的每个元素时就执行一次回调函数,并传递三个参数。
value 当前的数组元素
index 当前元素在数组中的位置
array 对数组的引用
此外,我们还可以传递一个可选的参数,作为每个函数调用时的上下文(this),看下面例子:
['_', 't', 'a', 'n', 'i', 'f', ']'].forEach(function (value, index, array) {
this.push(String.fromCharCode(value.charCodeAt() + index + 2))
}, out = []) out.join('')
// <- 'awesome'
这里使用了.join,这是我们还没有提及到的,但往后我们会再作介绍,在这个例子中,他可以连接数组中的不同元素,可以达到类似字符串拼接的效果。out[0] + '' + out[1] + '' + out[2] + '' + out[n].
我们不能中止forEach循环和抛出异常,在这些情景下,我们可以选择使用其他可用的方法。
使用 .some和.every来断言
=====
如果你曾使用过.Net的 enumerables,也许你熟悉.Any(x => x.IsAwesome) and .All(x => x.IsAwesome).
这些方法和.forEach非常相似,他们同样地给回调函数传递了value, index 和array, 你也同样的可以给他传入二个可选参数来作为回调函数的上下文。MDN是这样来描述.some的:
".some方法可以在遍历数组中的每个元素时执行回调函数,直到回调函数返回true为止,如果这个元素被发现,.some立即返回true。否则.some会返回false. 回调函数只对数组非空元素的索引调用,并不会对已经被删除或从未被指派的值调用"
max = -Infinity
satisfied = [10, 12, 10, 8, 5, 23].some(function (value, index, array) {
if (value > max) max = value
return value < 10
}) console.log(max)
// <- 12 satisfied
// <- true
回调函数会在满足条件value < 10时停止执行。.every也是同样的道理,但他的短路是发生在回调函数返回false时。
使用 .join and .concat 来合并
=====
.join方法通常会和.concat方法混淆。.join是创建一个通过分隔符来链接数组中各元素的字符串,如果不提供分隔符,他就会默认以逗号作用分隔符。.concat通过他的源数组创建一个新的数组。
.concat 可以传入多个参数: array.concat(val, val2, val3, valn)
.concat 是可以返回一个新的数组
array.concat() 如果不传入参数则将会返回一个新的浅拷贝数组。
浅拷贝意味着副本可以保存着源数组的对象引用。例如:
var a = { foo: 'bar' }
var b = [1, 2, 3, a]
var c = b.concat() console.log(b === c)
// <- false b[3] === a && c[3] === a
// <- true
使用 .pop, .push, .shift, and .unshift 来操作栈和队列
===
现在大家都知道可以通过.push方法来往数组中添加元素,但你是否知道.push可以传入多个参数,一次性把多个参数添加到数组后面。如:[].push('a', 'b', 'c', 'd', 'z')
.pop方法和.push方法刚好相反。他将会返回数组中的最后一个元素,并且同时从数组中删除这个元素。如果数组为空,则会返回void . (undefined)。使用.push和.pop,我可以非常容易地创建一个LIFO(last in first out) 的栈。
function Stack () {
this._stack = []
} Stack.prototype.next = function () {
return this._stack.pop()
} Stack.prototype.add = function () {
return this._stack.push.apply(this._stack, arguments)
} stack = new Stack()
stack.add(1,2,3) stack.next()
// <- 3
反之,我可以通过使用.unshift 和.shift来创建一个FIFO(fist in first out) 的队列。
function Queue () {
this._queue = []
} Queue.prototype.next = function () {
return this._queue.shift()
} Queue.prototype.add = function () {
return this._queue.unshift.apply(this._queue, arguments)
} queue = new Queue()
queue.add(1,2,3) queue.next()
// <- 1
使用.shift (或.pop) 可以容易地遍历数组。
list = [1,2,3,4,5,6,7,8,9,10] while (item = list.shift()) {
console.log(item)
} list
// <- []
使用 .map 映射模型
=========
.map在遍历数组中的每个元素时执行一次回调函数,并且会返回一个新的数组。回调函数只会对数组的元素索引执行,并不会对已删除或没元素的索引而执行。
Array.prototype.map方法和.forEach,.some和.every有着相似的地方:.map(fn(value, index, array), thisArgument)。
values = [void 0, null, false, '']
values[7] = void 0
result = values.map(function(value, index, array){
console.log(value)
return value
}) // <- [undefined, null, false, '', undefined × 3, undefined]
undefined × 3 的意思是.map不会在一个删除或者未定义的数组元素上执行,但他们会继续保留在结果数组上。映射是对数组的转化是非常有用的。看下面示例:
// casting
[1, '2', '30', '9'].map(function (value) {
return parseInt(value, 10)
})
// 1, 2, 30, 9 [97, 119, 101, 115, 111, 109, 101].map(String.fromCharCode).join('')
// <- 'awesome' // a commonly used pattern is mapping to new objects
items.map(function (item) {
return {
id: item.id,
name: computeName(item)
}
})
使用 .filter 来做查询
======
.filter在遍历数组中的每个元素时执行一次回调函数,并且回调函数返回的true时,他将会保存这当前元素,最后返回一个新数组。回调函数只会对数组的元素索引执行,并不会对已删除或没元素的索引而执行。不传递到回调函数的元素将会被简单的忽略,并且不会在新的数组中出现。
[void 0, null, false, '', 1].filter(function (value) {
return value
})
// <- [1] [void 0, null, false, '', 1].filter(function (value) {
return !value
})
// <- [void 0, null, false, '']
使用.sort 来做排序
========
如果不提供回调函数,元素将会通过转换为字符后并且按照在字典中的顺序来排序。例如在字典中"80"在"9"的前面,但如果按数字来排序,则9在80之前。
就像大多数的排序函数一样,Array.prototype.sort(fn(a,b))可以比较两个元素。并且会在以下三个情况中返回值。
如果 a 应该出现在 b 之前,则返回值小于0。
如果a 和b 相等,则返回0。
如果 a 应该出现在 b 之后,刚返回值大于0。
[9,80,3,10,5,6].sort()
// <- [10, 3, 5, 6, 80, 9] [9,80,3,10,5,6].sort(function (a, b) {
return a - b
})
// <- [3, 5, 6, 9, 10, 80]
使用 .reduce, .reduceRight 来计算
========
这两个方法都有着同样的特性:
.reduce(callback(previousValue, currentValue, index, array), initialValue).
在每一个回调函数执行时,previousValue将会被返回。初始化时initialValue将会被传入回调函数,currentValue包含着当前的元素,index表示该元素的在数组中的位置。array为数组的引用。
一个经典的.reduce例子就是加法函数。
Array.prototype.sum = function () {
return this.reduce(function (partial, value) {
console.log(partial, ",",value)
return partial + value
}, 0)
}; [3,4,5,6,10].sum()
// <- 28
如果说我们要合并一些字符串,我们可能会用到.join方法来达到目的。但是在下面这个例子中,.join方法就可能达不到我们的要求了,除非这些对象都有valueOf或者toString属性。但我们可以使用.reduce方法来轻松实现合并各对象为字符串。
function concat (input) {
return input.reduce(function (partial, value) {
if (partial) {
partial += ', '
}
return partial + value.name
}, '')
} concat([
{ name: 'George' },
{ name: 'Sam' },
{ name: 'Pear' }
])
注:reduce和reduceRight的区别是,reduce 是从数组左到右开始遍历,而reduceRight是从数组右到左开始遍历。
使用 .slice 来复制
======
Array.prototype.slice can be used to convert array-like objects into real arrays.
和.concat相似,可以通过不传递参数给.slice方法来复制源数组。.slice方法可以传入两个参数,一个是开始位置,另一个是结束位置。Array.prototype.slice也可以把类数组转为数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// <- ['a', 'b']
但是用.concat就达不到这样的目的了,因为他会把类数组放到一个真正的数组中。
Array.prototype.concat.call({ 0: 'a', 1: 'b', length: 2 })
// <- [{ 0: 'a', 1: 'b', length: 2 }]
除此之外,我们还可以把类数组转换为真正的数组之后,并且去除数组前面几个元素。
function format (text, bold) {
if (bold) {
text = '<b>' + text + '</b>'
}
var values = Array.prototype.slice.call(arguments, 2) values.forEach(function (value) {
text = text.replace('%s', value)
}) return text
} format('some%sthing%s %s', true, 'some', 'other', 'things')
// <- <b>somesomethingother things</b>
.splice 的用途
====
.splice也是一个常用的数组方法。你可以通过.splice来删除元素,插入新元素,并且可以调用一次.splice在同样的位置达到删除,插入元素的目标不。要注意的是,这个方法是会改变源数组。
var source = [1,2,3,8,8,8,8,8,9,10,11,12,13]
var spliced = source.splice(3, 4, 4, 5, 6, 7) console.log(source)
// <- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ,13] spliced
// <- [8, 8, 8, 8]
如果你有留意,他会返回已删除的元素。
var source = [1,2,3,8,8,8,8,8,9,10,11,12,13]
var spliced = source.splice(9) spliced.forEach(function (value) {
console.log('removed', value)
})
// <- removed 10
// <- removed 11
// <- removed 12
// <- removed 13 console.log(source)
// <- [1, 2, 3, 8, 8, 8, 8, 8, 9]
使用 .indexOf 来查找
=========
通过使用.indexOf方法,我们可以找到元素在数组中的位置。如果找不到,将会返回-1。如果要查找,通常我会这样写比较a === 'a' || a === 'b' || a === 'c',但在这个场景,你可以['a', 'b', 'c'].indexOf(a) !== -1。
要注意的是,如果是查找数组中的对象,那么你要提供相同的对象引用。第二个参数是表示从数组中的哪个位置开始搜索。
var a = { foo: 'bar' }
var b = [a, 2] console.log(b.indexOf(1))
// <- -1 console.log(b.indexOf({ foo: 'bar' }))
// <- -1 console.log(b.indexOf(a))
// <- 0 console.log(b.indexOf(a, 1))
// <- -1 b.indexOf(2, 1)
// <- 1
如果你希望反顺序查找,你可以使用.lastIndexOf。
in 操作符介绍
========
.indexOf 和 in操作符非常容易混淆。
var a = [1, 2, 5] 1 in a
// <- true, but because of the 2! 5 in a
// <- false
问题就在这里,in操作符是用于检查一个对象的键,而不是查找一个元素在数组中的位置。当然这比.indexOf快。
var a = [3, 7, 6] 1 in a === !!a[1]
// <- true
in操作符相乎是把传递进来的值转换为布尔值。!!表达式是可以把值隐式转换为布尔值。
关于.reverse
=========
这个方法是可以把数组中的元素位置反转。
var a = [1, 1, 7, 8] a.reverse()
// [8, 7, 1, 1]
这里并非返回一个副本,而是直接修改了数组的本身。
译自:
http://flippinawesome.org/2013/11/25/fun-with-javascript-native-array-functions/
Javascript数组方法(译)的更多相关文章
- 【译】你应该了解的JavaScript数组方法
让我们来做一个大胆的声明:for循环通常是无用的,而且还导致代码难以理解.当涉及迭代数组.查找元素.或对其排序或者你想到的任何东西,都可能有一个你可以使用的数组方法. 然而,尽管这些方法很有用,但是其 ...
- JavaScript数组方法--every、some、fill
接上一篇,JavaScript数组方法--concat.push,继续其他的数组方法. every:every() 方法测试数组的所有元素是否都通过了指定函数的测试. 先看其使用方法: functio ...
- JavaScript数组方法大全(推荐)
原网址:http://www.jb51.net/article/87930.htm 数组在笔试中经常会出现的面试题,javascript中的数组与其他语言中的数组有些不同,为了方便之后数组的方法学习, ...
- JavaScript 数组方法处理字符串 prototype
js中数组有许多方法,如join.map,reverse.字符串没有这些方法,可以“借用”数组的方法来处理字符串. <!doctype html> <html lang=" ...
- 2018.2.27 JavaScript数组方法应用
JavaScript数组方法应用 1.找出元素item在给定数组arr中的位置 function indexOf(arr,item){ return arr.indexOf(item); } func ...
- JavaScript数组方法详解
JavaScript数组方法详解 JavaScript中数组的方法种类众多,在ES3-ES7不同版本时期都有新方法:并且数组的方法还有原型方法和从object继承的方法,这里我们只介绍数组在每个版本中 ...
- JavaScript数组方法速查,32个数组的常用方法和属性
JavaScript数组方法速查手册极简版 http://30ke.cn/doc/js-array-method JavaScript数组方法速查手册极简版中共收了32个数组的常用方法和属性,并根据方 ...
- JavaScript数组方法大集合
JavaScript数组方法集合 本文总结一下js数组处理用到的所有的方法.自己做个笔记. 数组方法 concat() 合并两个或多个数组 concat()能合并两个或者多个数组,不会更改当前数组,而 ...
- 一站式超全JavaScript数组方法大全
一站式JavaScript数组方法大全(建议收藏) 方法一览表 详细操作 本人总结了JavaScript中有关数组的几乎所有方法(包含ES6之后新增的),并逐一用代码进行演示使用,希望可以帮助大家! ...
随机推荐
- 在linux下获取帮助
1.使用man手册页 man是一种显示Unix/Linux在线手册的命令.可以用来查看命令.函数或文件的帮助手册,另外它还可以显示一些gzip压缩格式的文件. 读者在遇到不懂的命令时,可以用man查看 ...
- express 4 中 session的处理(仅为博主笔记)
1.app.js var express = require('express') var app = express();var routers = require('./router/index' ...
- canvas画随机闪烁的星星
canvas画一颗星星: 规则的星星有内切圆和外切圆,每两个点之间的角度是固定的,因此可得到星星的每个点的坐标,画出星星. function drawStars(x,y,radius1,radius2 ...
- QuerySet创建新对象的方法和获取对象的方法
新建一个对象的方法有以下几种: Person.objects.create(name=name,age=age) p = Person(name="WZ", age=23) p.s ...
- 怎么去除google的 安全搜索
想要避开安全搜索 更改右上角的搜索设置,将搜索语言改为英文,然后保存搜索设置 第二次进入搜索设置里找Filter explicit results前的面的勾去掉即可.
- MySQL的备份的一些策略和方法的总结
1.一般使用的是mysqldump来进行备份,每次dump的数据是1000条,并且在这个过程中会进行锁表. (这种方式是逻辑备份,即直接将数据库中的数据导成sql语句进行备份的过程) 主要的使用方法: ...
- 如何做一个avalon组件
在avalon1.5中改用更直观的自定义标签来声明组件,废掉ms-widget,引入更强大的生命周期管理,可以让组件任意套嵌. 组件是由JS,HTML,CSS构成 JS 以AMD形式组织,引入HTML ...
- linux系统各目录存储的文件类型
/etc 存储各种配置文件 /etc/init.d/ 目录下包含许多系统各种服务的启动和停止脚本.具体可见:http://blog.csdn.net/gongweijiao/article/detai ...
- NXP开源自动驾驶计算平台Bluebox 打造现实无人汽车
知名半导体制造商恩智浦NXP已经准备好了自家的自动驾驶计算开源平台Bluebox,将为汽车制造商提供现成的一体化自动 驾驶计算解决方案.专为自动驾驶设备的BlueBox中央计算引擎.不仅能够为无人驾驶 ...
- jquery的常用ajax操作
$.ajax() 定义和用法 ajax() 方法通过 HTTP 请求加载远程数据. 该方法是 jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等.$.ajax() ...