Underscore.JS 之 消灭for循环
UnderScore.JS是一款对JavaScript内置对象具有高效多种处理方法的JS库文件。
文档
安装
安装Underscore.JS的方法如下:
- Node.js
npm install underscore --save
- bower
bower install underscore --save
上面的命令行指令中,--save的作用是直接把引用写到 package.json
以及 index.html
中,如果不加的话则须手动修改文件。
还有其他一些不常用的安装方法,有需要可用参考官方文档。
安装完成后,可用使用 npm list
或 bower list
来确保安装的正确性,并确保在 index.html
中具有相应的引用。
使用介绍
在本文中,将会介绍如何用简单的UnderScore.JS函数来替代原有的for循环编程习惯,可以极大减少代码量。
当然,UnderScore.JS的实际可用功能远远不止这一点。
现在,我们来构造一个简单的通讯录如下,命名为 phone_list
,实际上也可适用于任何的数组或者对象:
[{name:'张三',phone:'13311111111',from:'北京'},
{name:'李四',phone:'13322222222',from:'上海'},
{name:'王二',phone:'13333333333',from:'广州'},
{name:'刘一',phone:'13344444444',from:'北京'},
{name:'赵零',phone:'13355555555',from:'上海'}]
案例一
假设我现在需要给“王二”打电话,需要知道“王二”的手机号码,而数组本身没有直接的查询功能,所以一般的方法是:
for(var i=0; i<phone_list.length; i++) {
if(phone_list[i].name == '王二') {
return phone_list[i].phone;
}
}
return undefined;
上面我们构造了一个for循环,逐项查找 name
字段,找到“王二”时返回其手机号。就算法复杂度而言,在没有数据库的情况下,对对象数组的操作只能时顺序查找,并没有什么问题。但是,这样写有很多没有必要的内容,对于各种方法需要构造各种各样的for循环。那么有没有什么办法能够直接一个函数就完成上述功能呢?Underscore就给了我们这样一个机会。
使用UnderScore.JS方法的代码如下:
return _.findWhere(phone_list, {name: "王二"}).phone;
_.findWhere
函数具有两个参数,第一个为需要查找的列表(数组),第二个为查找的条件(对象),返回值为列表中找到的第一个满足条件的元素。本例中为“王二”的通讯录对象,然后通过 .phone
获取其电话号码。
原本的6行代码现在只需要1行完成,可用大大减少不必要的工作量;同时代码的可读性也大大增加,减少不必要的错误概率。
案例二
假如我突然心血来潮,要把通讯录里面所有人的手机号码前面都加上 +86
,先不考虑有木有这样的强迫症患者,现在大多数人首先想到的应该还是for循环吧?是的,for循环确实基本是万能的,便利一个数组当然也是小事一桩:
for(var i=0; i<phone_list.length; i++) {
phone_list[i].phone = "+86".concat(phone_list[i].phone);
}
for循环的忠实支持者可能会说,这次我在for循环里面只用了一行就搞定了~
当然,使用Underscore.JS同样能够做到:
_.each(phone_list, function (element) {
element = "+86".concat(element.phone);
});
_.each()
函数具有两个参数,第一个是需要遍历的对象,第二个是对其中每个元素的操作内容。
总的来说这里二者的代码量相当,当相对而言后者还是要略显简介~
案例三
有一天我突然到了北京,然后我想知道有那些朋友是北京的(连是哪的都不知道还好意思叫朋友么...)。如果使用传统的for循环,思路就是新建一个数组,如果是北京的就放进去,代码如下:
var result = [];
for(var i=0; i<phone_list.length; i++) {
if(phone_list[i].from == '北京') {
result.push(phone_list[i]);
}
}
return result;
看了上面的例子大家应该发现,一旦需要用到 if
,for循环就输定了...
使用Underscore.JS的代码明显要短很多:
return _.where(phone_list, {from: "北京"};
_.where()
的用法和 _.findWhere
相同,不同的是前者返回所有满足条件的元素构成的数组,而后者只返回第一个满足的元素。
案例四
如果我还是想设定一些条件来查找通讯录,但条件又不是具有某一键值对,那又该怎么办呢?
还是老样子,先来for循环的方法:
var result = [];
for(var i=0; i<phone_list.length; i++) {
if(phone_list[i].phone.substring(0,3) == '133') {
result.push(phone_list[i]);
}
}
return result;
这个我们当然也还是可以用Underscore.JS来解决:
return _.filter(phone_list, function (person) {
person.phone.substring(0,3) == '133'
});
_.filter()
函数中,相当于把 _.where()
需要满足的键值对换成人为设定的布尔函数,返回的是布尔函数为真的所有元素构成的集合。
本文的内容到这里就结束了,但是Underscore.JS的使命才刚刚开始。看完这些,你是否已经对Underscore.JS心动了呢?
本站地址: http://trotyl.github.io/