(二)underscore.js框架Utility类API学习以及模型template的详细介绍

本文介绍的是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 &amp; Moe"

unescape_.unescape(string) 
The opposite of escape, replaces &amp;&lt;&gt;&quot;&#96; and &#x27;with their unescaped counterparts.

_.unescape(‘Curly, Larry &amp; 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函数,这个函数也比较复杂,而且主要是框架内部使用。后续再专门研究这个函数,单独写一篇博文。


(二)underscore.js框架Utility类API学习以及模型template的详细介绍

上一篇:x264源码分析之P帧的16x16宏块的帧间分析


下一篇:Linux中/proc目录下文件详解(转贴)