本文介绍的是underscore.js提供的Utility Functions。
noConflict_.noConflict()
Give control of the "_" variable back to its previous owner. Returns a reference to theUnderscore object.
这个函数主要是为了解决underscore.js与其他框架或js名字冲突的问题。我们知道:underscore.js使用全局对象_,如果在underscore框架加载前,已经有了这么一个全局变量会怎么样呢?
<html> <head> <script> // 在underscore.js框架加载前运行,目的是验证_.noConflict(); var _ = "11"; </script> <script src="underscore-1.7.0/underscore.js"></script> <script> //underscore是返回的underscore.js封装对象 var underscore = _.noConflict(); alert(underscore.VERSION); // _之前是什么,现在就还原成什么. alert(_);//11 </script> </head> <body> </body> </html>
首先定义了一个全局变量_,当underscore框架加载后,_之前的值被覆盖。当调用_.noConflict()之后,该函数返回是underscore封装的对象,仍然可以使用这个函数的返回值调用underscore.js提供的API。_被还原成underscore.js加载之前的值,就是11。
identity_.identity(value)
Returns the same value that is used as the argument. In math: f(x) = x
This function looks useless, but is used throughout Underscore as a default iteratee.
var moe = {name: ‘moe‘}; moe === _.identity(moe); => true
该函数啥也不做,就是直接返回传递给他的参数值,即数学中的f(x) = x。
constant_.constant(value)
Creates a function that returns the same value that is used as the argument of_.constant.
var moe = {name: ‘moe‘}; moe === _.constant(moe)(); => true
该constant()返回值是一个函数(这个函数返回的就是传递给constant()函数的参数)。
noop_.noop()
Returns undefined irrespective(不管) of the arguments passed to it. Useful
as the default for optional callback arguments.
obj.initialize = _.noop;
noop就是no operation的缩写,就是一个空函数,啥也不干,返回值是undefined或者说是没有返回值。有点像null object模式,避免使用者判空。
times_.times(n,
iteratee, [context])
Invokes the given iteratee function n times.
Each invocation of iteratee is
called with an index argument.
Produces an array of the returned values.
var result = _.times(3, function(i){return i * 10;}) console.log("times=" + result);// 0,10,20 result = _(3).times(function(i){ return i * 10; }); console.log("times=" + result);// 0,10,20
上面这2种写法是等价的
random_.random(min,
max)
Returns a random integer between min and max, inclusive. If you only pass one argument, it will return a number between 0 and
that number.
_.random(0, 100); => 42
mixin_.mixin(object)
Allows you to extend Underscore with your own utility functions. Pass a hash of {name:
function} definitions to have your functions added to the Underscore object, as well as the OOP wrapper.
_.mixin({ capitalize: function(string) { return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase(); } }); _("fabio").capitalize(); => "Fabio"
uniqueId_.uniqueId([prefix])
Generate a globally-unique id for client-side models or DOM elements that need one. Ifprefix is passed, the id will be appended to it.
_.uniqueId(‘contact_‘); => ‘contact_104‘
返回id,在当前html是唯一的;或者说:同一个_对象内是唯一的
escape_.escape(string)
Escapes a string for insertion into HTML, replacing &, <, >, ", `,
and ‘characters.
_.escape(‘Curly, Larry & Moe‘); => "Curly, Larry & Moe"
unescape_.unescape(string)
The opposite of escape, replaces &, <, >, ", ` and 'with
their unescaped counterparts.
_.unescape(‘Curly, Larry & Moe‘); => "Curly, Larry & Moe"
result_.result(object,
property)
If the value of the named property is a function then invoke it with the object as context; otherwise, return it.
var object = {cheese: ‘crumpets‘, stuff: function(){ return ‘nonsense‘; }}; _.result(object, ‘cheese‘); => "crumpets" _.result(object, ‘stuff‘); => "nonsense"
now_.now()
Returns an integer timestamp for the current time, using the fastest method available in the runtime. Useful for implementing timing/animation functions.
_.now(); => 1392066795351
template_.template(templateString,
[settings])
Compiles JavaScript templates into functions that can be evaluated for rendering. Useful for rendering complicated bits of HTML from
JSON data sources. Template functions can both interpolate variables, using <%= … %>,
as well as execute arbitrary JavaScript code, with <% … %>.
If you wish to interpolate a value, and have it be HTML-escaped, use <%- … %> When
you evaluate a template function, pass in a data object
that has properties corresponding to the template‘s free variables. The settingsargument
should be a hash containing any _.templateSettings that
should be overridden.
1、模板很类似JS模板引擎,如artTemplate、Handlebars、Mustache等JS模板框架,主要是为了避免在javascript中拼接DOM字符串(非常的繁琐,而且很容易出错)。underscore.js提供的模板有三种使用方式:即<%= %>和<%- %>和<% %>。
// 替换普通变量 var varcompiled = _.template("<h2><%= word %></h2>"); console.log("template=" + varcompiled({word : "Hello World"})); // 变量的值包含五个特殊字符(& < > " ' /),就需要用<%- ... %>转义 var escape = _.template("<h2><%- word %></h2>"); console.log("template=" + escape({word : "Hello & World"})); //JavaScript命令可以采用<% … %>的形式插入 var compiled = _.template("<% console.log('Hello ' + epithet); %>"); compiled({epithet: "hehe"});
2、改变变量默认名称
//改变内部变量名称 //templateString中的所有变量,在内部都是obj对象的属性,而obj对象就是指第二个参数data对象。 // 下面语句是等同的。 console.log(_.template("Hello <%=user%>!")({ user: "jane" })); console.log(_.template("Hello <%=obj.user%>!")({ user: "jane" })); console.log(_.template("Hello <%=data.user%>!",{variable: 'data'})({ user: "jane" }));
3、通过编译后函数的source属性,查看模板编译的源码,便于定位问题
// 查看预编译的源码 console.log(_.template("Hello <%=user%>!").source);
4、模板格式的设置
之前提到过,underscore提供3种格式的模板<%= %>和<%- %>和<% %>。对应的源码如下:
// By default, Underscore uses ERB-style template delimiters, change the // following template settings to use alternative delimiters. _.templateSettings = { evaluate : /<%([\s\S]+?)%>/g, interpolate : /<%=([\s\S]+?)%>/g, escape : /<%-([\s\S]+?)%>/g };
我们知道<%= %>这种格式与JSP中嵌入java代码使用的方式一致,如果在JSP中写java代码和underscore模板,那么会冲突。我们通过设置,可以改变underscore模板的格式。下面的代码,用{}这种格式替换<%= %>
var newformat = _.template("Hello {user}!",{interpolate : /{([\s\S]+?)}/g}); console.log("result=" + newformat({ user: "jane" }));
5、还有一点值得注意,就是underscore提供的三种格式是可以一起使用的,这样的话,模板里面就可以写if、while等逻辑控制了。比如有这么一个对象,{"flag":true,"name":"aty","age":20},我们的模板需要根据flag的值进行判断,如果是true,则返回name的值,如果是false则返回age的值。
//很类似于jsp中写java var tpt = "<% if (flag){ %>" + "<%= name %>" + "<% } %>"; + "<% else {%>" + "<%= age %>" + "<% } %>"; var resultFunc = _.template(tpt); console.log("result=" + resultFunc({"flag":true,"name":"aty","age":20}));
可以看到:这种使用方式,很类型与JSP中写java代码,如果逻辑比较复杂,括号的嵌套层次比较多,那么这种方式写出的代码几乎不可读。上面的代码功能其实就是
if(flag) { return name; } else { return age; }
可以看到直接写javascript代码简单的多。这也是underscore模板的不足之处,虽然支持写javascript代码,但是非常复杂。等有时间我再去学习了专门的JS模板引擎,看它们是否能够实现的更优雅。
最后,underscore_1.7.0版本中utility还提供了一个iteratee函数,这个函数也比较复杂,而且主要是框架内部使用。后续再专门研究这个函数,单独写一篇博文。