Backbine.js實戰第二章----Underscore

我叫阿狸貓發表於2014-10-22

1.Underscore物件封裝

Underscore沒有對原生JavaScript物件進行封裝,而是呼叫_()方法進行封裝,一旦封裝完成,原生JavaScript物件便成為一個Underscore物件。也可以通過Underscore物件的value()方法獲取原生JavaScript物件中的資料。

var data = {
		name:'皮卡丘',
		email:'12345@qq.com'
	}
var object = _(data);//封裝成Underscore物件
alert(object.value().name+"---"+object.value().email);


在上述程式碼中,先定義了一個原生JavaScript物件data,該物件中包含name、email兩項屬性,並設定了相應的屬性值;然後,通過_()方法將原生的data物件轉成一個名為"object"的Underscore物件;最後,在網頁中彈出Underscore物件object呼叫value()方法獲取原生JavaScript物件data中兩項屬性值的內容。


一旦使用_()方法封裝成Underscore物件之後,就能通過value()方法訪問封裝前的原生JavaScript資料,還可以直接使用Underscore庫中現存的函式,如下程式碼所示。

var arr = [15,26,37];
var obj = _(arr);//封裝成Underscore物件
alert("最大:"+obj.max()+";最小:"+obj.min());

在上述程式碼中,先定義一個名為"arr"的陣列,然後通過_()方法將陣列轉成一個名為“obj”的Underscore物件,最後obj物件呼叫Underscore庫中的max()和min()函式在網頁中彈出陣列的最大和最小元素值。


2.2集合

1.each()和map()函式

Underscore中的each()和map()函式有一個共同特徵,就是根據一定的條件遍歷集合中的每個元素。它們又有區別,each()函式在操作時,只是執行按照過濾條件遍歷每個列表元素的動作,該動作並無返回內容;而map()函式在操作時,不僅按照過濾條件執行遍歷元素的操作,而且返回一個新的過濾後的集合內容,接下來進行逐個進行說明。

(1).each()函式

呼叫格式:

_,each(list,iterator,[context])

該函式的功能是:根據iterator迭代器提供的過濾條件,遍歷list列表中的每一個元素,每遍歷一次,產生一個迭代函式。此外,iterator迭代器還可以與可選項context上下文物件繫結。示例如下。

_.each([1,2,3,4,5,6,7],function(n){
	if(n%2){
		console.log(n);
	}
});

(2).map()函式

呼叫格式:

_.map(list,iterator,[context])

該函式的功能是:根據iterator迭代器中的函式,遍歷list列表中的每一個元素,在完成列表元素遍歷之後,該函式將返回一個陣列物件。示例如下。

var arr = _.map([1,2,3,4,5,6,7],function(n){
	if(!(n%2)){
		return n;
	}
});
for(var p in arr){
	console.log(arr[p]);
}

在上述程式碼中,先由map()函式通過iterator迭代器從list列表中返回一個偶數陣列arr。在arr陣列中,雖然iterator迭代器使用了過濾條件,但返回的arr陣列中元素的總數量與原列表一樣。如果list列表中存在不符合iterator迭代器中條件的元素,在arr陣列中將使用"undefined"來表示這些元素的值,以確保返回的arr陣列與原列表中元素總數量保持一致。


總結:

each()和map()函式都是藉助iterator迭代器遍歷list列表中的每個元素,each()僅是按照iterator迭代器的規則操作list列表中的全部元素,函式本身並不返回資料;而map()函式不僅按照iterator迭代器的規則操作元素,而且返回一個新的陣列,這就是兩個函式間最大的區別。


無論each()或map()函式,如果引數list列表是一個JavaScript物件,iterator迭代器遍歷時的引數則變為(value,key,list)。示例如下。

var obj = {
	a:'1',
	b:'2',
	c:'3'
};
_.each(obj,function(v,k,obj){//注意第一個引數是value,第二個引數才是key
	return console.log(k+"->"+v);
});


在上述程式碼中,先定義一個名為obj的JSON物件,它的內部含有3個屬性a,b,c,並對應相應的屬性值,然後使用each()函式操作物件中的屬性。由於此時list列表引數是一個物件,因此,iterator迭代器中自定義的函式引數變為(v,k,obj),並在函式體中使用console.log方法輸出物件中屬性名稱和對應的屬性值。




2.find()和filter()函式

find()和filter()都屬於查詢或過濾性函式,都是在指定的列表或物件中,尋找符合iterator迭代器中自定義函式規則的元素項。如果找到,find()函式返回首個與條件相符的元素值;如果沒有找到,則返回"undefined"。而在filter()函式中,如果找到,則返回一個與條件相符的陣列;如果沒有找到,則返回一個空陣列。接下來我們逐一進行介紹。


(1).find()函式

呼叫格式:

_.find(list,iterator,[context])

該函式的功能是:根據iterator迭代器中的自定義函式條件,在list列表中查詢符合條件的第一個元素項,如果找到,返回第一個元素項,否則返回"undefined"。示例如下。

var blnfind = _.find([2,4,6,8,10,12],function(n){
	return (!(n%2==0));
});
console.log(blnfind==undefined?"未找到":blnfind);

上述程式碼中,find()函式的iterator迭代器引數中,查詢條件為"!(n%2==0)",即查詢引數list列表中的奇數元素。如果找到,在控制檯中輸出首個符合查詢條件的元素項,否則輸出"未找到"的字樣。由於上述程式碼中的list列表中不存在奇數項,因此將會輸出"未找到"字樣。


(2).filter()函式

呼叫格式:

_.filter(list,iterator,[context])

該函式的功能是:根據iterator迭代器中的自定義函式條件,在list列表中過濾符合條件的元素項。如果找到,則返回含有元素項的陣列;如果沒有找到,則返回一個空陣列。示例如下。

var arrfind = _.filter([1,4,3,6,5,8],function(n){
	return (!(n%2==0));
});
console.log(arrfind.length!=0?arrfind:"未找到");

在上述程式碼中,在filter()函式的iterator迭代器引數中,過濾條件為"!(n%2==0)",即過濾引數list列表中的奇數元素,其中arrfind為過濾後返回的結果值。如果“arrfind.length!=0”成立,表示找到了,為控制檯中輸出全部符合過濾條件的元素項,否則輸出“未找到”的字樣。

3.max()和min()函式

(1).max函式

呼叫格式:

_.max(list,[iterator],[context])

該函式的功能是:返回list列表中的最大值。示例如下。

var arr = [1,2,3,4,5];
console.log("最大值:"+_.max(arr));


(2).min函式

呼叫格式:

_.min(list,[iterator],[context])

該函式的功能是:返回list列表中的最小值。示例如下。

var stu = [
	{name:'張三',score:60},
	{name:'李四',score:40},
	{name:'王五',score:80},
];
var min = _.min(stu,function(n){
	return n.score;
});
console.log("最小分數值姓名為:"+min.name);

在上述程式碼中,stu是一個JSON格式的陣列,在使用min()函式獲取該陣列最小值時,增加了可選項引數iterator迭代器。該iterator迭代器是一個返回陣列中score屬性值的自定義函式,當執行min()函式時,先執行iterator迭代器中的自定義函式,返回一個包含陣列中全部score屬性值的新list列表,再從該列表中獲取最小分數值。由於“李四的分數值最小,瀏覽器的控制檯中將輸出“李四字樣。


4.sortBy()和groupBy()函式

(1).sortBy函式

呼叫格式:

_.sortBy(list,iterator,[context])

該函式的功能是:返回一個按升序排列的副本列表。排序的規則可以是iterator迭代器中自定義的函式,也可以是一個與元素屬性相關的字串,如“length”。示例如下。

var stu = [
	{name:'張三',score:60},
	{name:'李四',score:40},
	{name:'王五',score:80},
];
var sort = _.sortBy(stu,function(n){
	return n.score;
});
for(var p in sort){
	console.log(sort[p].name+"->"+sort[p].score);
}

在上述程式碼中,執行sortBy()函式排序後,獲得一個按分數升序排列的副本列表物件,並將該物件儲存至sort變數中,然後通過for語句將排序後的各元素內容輸出至瀏覽器控制檯中。

(2).groupBy()函式

呼叫格式:

_.groupBy(list,iterator,[context])

該函式的功能是:將list列表按iterator迭代器中自定義的函式或一個元素屬性相關的字串進行分組分割,分割後得到多個子列表。示例如下。

var stu = [
	{name:'張三',score:60},
	{name:'李四',score:40},
	{name:'王五',score:80},
];
var group = _.groupBy(stu,function(n){
	return n.score>60;
});
console.log(group);

在上述程式碼中,通過iterator迭代器中的自定義函式,對stu物件中的“score”元素按大於60的規則進行分組,然後在瀏覽器的控制檯中輸出分組後的物件group。

從上圖中可以清楚地看出,輸出的group物件根據過濾條件(大於60)被分割成false和true兩個部分,false部分是包含兩個元素的列表物件,true部分則是包含一個元素的列表物件。


2.3陣列

2.3.1first()和last()函式

在Underscore中,first()和last()是處理陣列最常用的兩個函式。前者可以獲取陣列中的首個元素或指定位數的前面陣列,後者可以返回陣列中的最後一個元素或指定位數的後面陣列。接下來我們逐一進行說明。


1.first()函式

呼叫格式:

_.first(array,[n])

該函式的功能是:返回陣列的第一個元素。如果設定可選項n的值,將返回一個包含前n項元素的新陣列。示例如下。

var stu = [
	{name:'張三',score:60},
	{name:'李四',score:40},
	{name:'王五',score:80},
];
var first = _.first(stu,2);
console.log(first);

在上述程式碼中,通過first()函式返回stu陣列物件中前兩項的元素內容,並將它輸出到瀏覽器的控制檯中。


2.last()函式

呼叫格式:

_.last(array,[n])

該函式的功能是:返回陣列的最後一個元素。如果設定了可選項n值,將返回一個包含後n項元素的新陣列。示例如下。

var stu = [
	{name:'張三',score:60},
	{name:'李四',score:40},
	{name:'王五',score:80},
];
var last = _.last(stu,2);//如果第二個引數大於陣列長度,也只顯示3個。
console.log(last);

在上述程式碼中,通過last()函式返回stu陣列物件中後兩項的元素內容,並將它輸出到瀏覽器的控制檯中。


2.3.2 indexOf()和lastIndexOf()函式

在Underscore中,如果要查詢某個元素是否存在於陣列中,可以使用indexOf()和lastIndexOf()這兩個函式。前者是查詢元素首次出現的位置,後者是查詢元素最後一次出現的位置,如果不存在,都返回-1,否則返回被查詢元素在陣列中的位置,即元素的索引號,該索引號從0開始。接下來分別對這兩個函式進行介紹。


1.indexOf()函式

呼叫格式:

_.indexOf(array,value,[isSorted])

該函式的功能是:返回value值在陣列array中首次出現的位置。如果存在,返回value值在陣列array中的索引號;如果不存在,則返回-1值。在一個較大的陣列array中,如果該陣列已經排序過,可以使用可選引數isSorted,該引數用於加速查詢的過程。示例如下。

var stu = ['張三','李四','王五'];
var find = _.indexOf(stu,'李四');
console.log(find);

上述程式碼通過indexOf()函式在陣列stu中查詢“李四”元素,並將查詢結果顯示在瀏覽器的控制檯中。由於元素“李四”包含在陣列stu中,因此將在控制檯輸出被查詢元素在陣列首次出現的位置,即索引號為1。

注意:indexOf()函式是全字匹配,陣列中的元素內容必須與查詢字元value完全一樣才能算是存在,否則都將返回-1,表示沒有找到。


2.lastIndexOf()函式

呼叫格式:

_.lastIndexOf(array,value,[fromIndex])

該函式的功能是:返回value值在陣列array中最後一次出現的位置。如果存在,返回value值在陣列array中的索引號;如果不存在,則返回-1值。可選項fromIndex表示指定查詢的最大索引號位置。示例如下。

var stu = ['李四','王二','李四','張三','李四'];
var find = _.lastIndexOf(stu,'李四',3);
console.log(find);

在上述程式碼中,陣列stu包含3個不同索引號位置而內容都為“李四”的元素。當使用lastIndexOf函式在最大索引號為3的範圍內查詢“李四”這個元素時(在索引號小於3的範圍裡找),該元素最後一次出現的索引號位置則為2,最後將該值輸出至瀏覽器的控制檯中。


2.3.3 without()和union()函式

在Underscore中,如果要排除陣列中的某些元素或將多個陣列進行拼接,可以使用without()或union()函式。前者是一個排他函式,可以移除陣列中指定的某些元素,返回一個新的陣列;後者則可以將多個元素進行連線,除掉重複元素項,同樣也返回一個新的陣列。接下來,分別對這兩個函式的使用方法進行詳細介紹。


1.without()函式

呼叫格式:

_.without(array,[*values])

該函式的功能是:返回一個不包含可選項values元素的新陣列,引數array為原陣列,可選項*values為原陣列中的各個元素。示例如下。

var newarr = _.without([40,60,50,40,4],4,40);
console.log(newarr);


在上述程式碼中,without()函式返回的新陣列不包含4和40兩個元素。在執行該函式時,將在原陣列的基礎之上,返回一個不包含4和40兩個元素的新陣列newarr,並將該陣列輸出到瀏覽器的控制檯中。


2.union()函式

呼叫格式:

_.union(*arrays)

該函式的功能是:返回組合後的陣列列表。引數arrays是一個或多個陣列列表。如果多個陣列中有重複的元素,在返回的組合陣列列表中僅顯示一次。示例如下。

var newarr = _.union([1,2,3],[3,4,5],[5,6,7]);
console.log(newarr);

在上述程式碼中,union()函式將3個陣列進行合併重組,各陣列中相同元素項僅保留一次,因此,在瀏覽器控制檯輸出的陣列元素為“1,2,3,4,5,6,7”。


2.4函式

2.4.1 delay()函式

在Underscore庫中,delay()函式的功能類似於JavaScript中的setTimeout()方法,即表示推遲一段程式碼或一個函式的執行。它的呼叫格式如下。

_.delay(function,wait,[*arguments])

其中,引數function為自定義的函式,wait為設定延遲的時間(單位為毫秒),可選引數arguments為呼叫自定義函式時所需的實參(如果函式有引數)。示例如下。

var fun = function(n){
	console.log("你輸入的是:"+n);
}
_.delay(fun,2000,"哈哈哈哈");

在上述程式碼中,先定義一個函式fun,該函式的功能是在控制檯中輸出使用者輸入的任意字元內容。然後呼叫delay()函式,在延時2000毫秒後,執行fun函式,在執行時,將實參“哈哈哈哈”傳入形參n。最後瀏覽器的控制檯輸出如上圖所示。


2.4.2 once()函式

在Underscore庫中,執行once()函式類似於對變數進行打包初始化的過程。once()函式僅執行一次,再次執行時就無效了,因為,once()函式常用於對專案變數進行初始化賦值。

其呼叫格式如下。

_.once(function)

其中,引數function是一個函式的名稱,執行once()函式時,將呼叫名稱為function的函式。再次執行once()函式時,將不再呼叫該函式,僅執行一次。示例如下。

var num;
var str;
var fun = function(){
	num = 0;
	str = "1";
	console.log("初始化成功!");
}
var init = _.once(fun);//返回值是一個函式
//_.once(fun); //這個並不是呼叫的意思   .once(fun)()這個才表示呼叫
init();//這個才表示呼叫
console.log("初始化後值->num:"+num+";str:"+str);

在上述程式碼中,先定義兩個變數num和str,然後自定義一個函式fun。在該函式中,對已定義的兩個變數進行初始化賦值,賦值完成後在控制檯輸出“初始化成功!”的字樣。

最後將once()函式呼叫時的返回值(一個函式)儲存在init變數中。由於該返回值是一個函式,當呼叫該函式時,將執行自定義函式fun的初始化功能,在初始化完成後,再將兩個變數num和str的值顯示在瀏覽器的控制檯中。

2.4.3 wrap()函式

在Underscore庫中,wrap()函式的作用是包裝,包裝方式是把函式本身包裝至wrapper(包裝外層)中。在呼叫時,函式本身僅作為wrapper(包裝外層)的一個引數進行傳入。

具體呼叫格式如下。

_.wrap(function,wrapper)

其中,引數function是被包裝的函式,wrapper是包裝外層,它也是一個函式,但這個函式的引數就是被包裝的函式本身(第一個引數)。示例如下。

var input = function(n,s){
	return s?n+",先生":n+",女士";
}
input = _.wrap(input,function(input){
	return "你好,"+input("皮卡丘",1)+",歡迎來到Backbone世界!";
});
console.log(input());

在上述程式碼中,先自定義一個iuput函式,該函式有兩個引數n和s,前者用於傳遞使用者輸出的“姓名”字元內容,後者用於傳遞“性別”。當“性別”為非0時,表示“男”,便在返回的“姓名”字元內容後新增“先生”字樣,否則表示“女”,將在返回的“姓名”字元內容後新增“女士”字樣。

接下來,呼叫wrap()函式對自定義的input函式進行包裝。在包裝時,input函式作為wrapper(包裝外層)函式的一個引數進行資料傳遞,並在input函式前後新增了其他字串內容,通過return語句一起返回給呼叫函式。


2.4.4 compose()函式
在Underscore庫中,compose()函式的功能是返回一個經過多個函式組合後的列表,用於計算在數學中一些比較複雜的運算,其呼叫格式如下。

_.compose(*functions)

其中,引數*functions表示多個引數,compose()函式可以將這些函式以一種有序的包含方式進行組合,例如引數*function中依次包含A、B兩個函式。當執行compose()函式時,過程是這樣的:先呼叫B函式,再將它的返回值作為A函式的引數,即A(B())。如果依次包含A、B、C三個函式,則執行過程是:A(B(C ())),依此類推。示例如下。

var A = function(a1){
	return a1*a1;
}
var B = function(b1){
	return b1*b1;
}
var C = function(c1){
	return c1*c1;
}
var D = _.compose(A,B,C);
console.log("最終結果為:"+D(2));
在上述程式碼中,先自定義3個函式,分別是A、B、C,它們的功能都是計算輸入引數的平方,然後呼叫compose()函式將上述的3個函式按照包含的方式進行組合,並將組合後返回的結果賦予函式D。最後使用輸入值2呼叫函式D,並將返回的結果顯示在瀏覽器的控制檯中。

從上圖中可以看出,當使用輸入值2呼叫函式D時,其最終的結果為256,該值的計算過程為:2*2=4,4*4=16,16*16=256,即按照A(B(C()))順序進行執行。


2.5物件

2.5.1 keys()和values()函式

在Underscore庫中,有許多物件的組成格式為key/value方式,針對這種現象,如果需要獲取它的全部key值名稱或value值,可以通過呼叫keys()和values()函式,前者返回一個包含全部key值名稱的陣列,後者返回一個包含全部value值的陣列,下面逐一進行介紹。


1.keys()函式

呼叫格式:

_.keys(object)

該函式的功能是:檢索並返回物件的屬性名稱,返回格式為陣列。引數object表示任意一個組成格式為key/value的物件。示例如下。

var info = {
	name:'皮卡丘',
	sex:'男',
	email:'111@qq.com'
}
var arrkey = _.keys(info);
console.log(arrkey);

在上述程式碼中,先自定義一個名稱為info的物件,包含3個key屬性name、sex、email;然後將info物件作為引數執行keys函式,並將返回的陣列儲存至變數arrkey中;最後將該變數在瀏覽器的控制檯中輸出。


2.valuse()函式

呼叫格式:

_.values(object)

該函式的功能是:返回物件的屬性值,返回格式為陣列。其中引數object表示任意一個組成格式為key/value的物件。示例如下。

var info = {
	name:'皮卡丘',
	sex:'男',
	email:'111@qq.com'
}
var arrvalue = _.values(info);
console.log(arrvalue);

在上述程式碼中,呼叫valuse()函式將獲取物件的屬性值儲存至變數arrvalue中,最後將該變數在瀏覽器的控制檯中輸出。


2.5.2 pick()和omit()函式

在Underscore庫中,如果要挑選和排除物件中的任意key屬性,可以使用pick()和omit()函式,前者可以從指定的物件中挑選出需要的任意key屬性,後者能夠從指定的物件中排除不需要的任意key屬性,兩者都返回一個新的物件。接下來分別進行介紹。


1.pick()函式

呼叫格式:

_.pick(object,*keys)

該函式的功能是:返回一個只有列入挑選key屬性的物件。其中,引數object為JSON格式的物件,*keys表示多個需要挑選出來的key屬性。示例如下。

var data = {
	A:1,
	B:2,
	C:3,
	D:4,
}
var newdata = _.pick(data,'B','C');
console.log(newdata);

在上述程式碼中,先定義一個名為data的物件,該物件中包含4個屬性,分別為A、B、C、D;然後呼叫pick()函式,挑選key的屬性為B、C,並將返回的物件賦予newdata;最後,在控制檯輸出該物件的內容


2.omit()函式

呼叫格式:

_.omit(object,*keys)
該函式的功能是:返回一個沒有列入排除key屬性的物件。其中,引數object為JSON格式的物件,*keys表示多個需要排除掉的key屬性。示例如下。

var data = {
	A:1,
	B:2,
	C:3,
	D:4,
}
var newdata = _.omit(data,'B','C');
console.log(newdata);

在上述程式碼中,呼叫omit()函式,排除key的屬性為B、C,將返回的物件賦予變數newdata,並在控制檯輸出該物件的內容。


2.5.3 defaults()函式

在Underscore庫中,可以通過defaults()函式設定物件的預設屬性值,如果這些預設的屬性被重置,則使用defaults()函式設定的屬性值無效,以重置後的值為準。其呼叫格式如下。

.defaults(object,*defaults)

該函式的功能是:返回一個設定了預設屬性內容的物件。其中,引數object為設定預設屬性的物件,*defaults為需要設定的預設屬性列表。示例如下。

var info = {};
info = _.defaults(info,{
	name:'',
	email:'111@qq.com'
});
info.name = "皮卡丘";
console.log(info);

在上述程式碼中,先定義一個名為info的空物件,然後呼叫defaults()函式為空物件設定預設屬性內容。完成設定後,再重置info物件的“name”屬性值,最後在瀏覽器的控制檯中輸出整個info物件的內容。


2.5.4 has()函式

在Underscore庫中,has()是一個很實用的函式,它可以檢測出JSON格式的物件中,是否存在某個屬性(key)值。如果存在,返回true,否則返回false。has()函式常用於呼叫物件的某屬性之前的檢測,通過該功能可以避免呼叫物件空屬性的錯誤,它的呼叫格式如下。

_.has(object,key)

該函式的功能是:檢測物件中是否包含給定的屬性(key),結果返回true或false。其中,引數object為物件,key表示物件中包含的屬性名稱。示例如下。

var info = {
	name:'皮卡丘',
	sex:'男',
	email:'111@qq.com'
}
var strShow;
if(_.has(info,'score')){
	strShow = info.score;
}else{
	strShow = "物件中不包含該屬性!";
}
console.log(strShow);

在上述程式碼中,先自定義一個名為info的JSON格式物件和一個用於輸出的字串變數“strShow”,然後呼叫has()函式檢測物件中是否包含score屬性。如果存在,將該屬性值賦予變數“strShow”,否則將錯誤提示資訊賦予變數。最後,在瀏覽器控制檯中輸出該變數的內容。

從上圖可以看出,由於info物件中不存在名稱為“score”的屬性,因此在瀏覽器的控制檯中輸出錯誤提示資訊。如果不使用has()函式進行屬性檢測,而直接訪問物件的屬性,將出現“undefined”異常。


2.6功能

2.6.1 random()函式

在Underscore庫中,random()函式的功能是獲取指定數字範圍內的隨機數。與傳統的JavaScript獲取隨機數程式碼相比較,random()函式更簡單。該函式的預設最小範圍數字為0,該值可以省略,只設定一個最大範圍值,此時將返回一個從0到這個最大範圍值的隨機數。

其呼叫格式如下。

._random(min,max)

該函式的功能是:返回一個在最小值和最大值之間的隨機數。其中,引數min、max分別表示生成隨機數的最小和最大範圍數值。最小範圍數值可以省略,如果省略,表示它的最小範圍值為0.示例如下。

var intdef = _.random(10);
var intnum = _.random(10,20);
console.log("兩個隨機數分別為:"+intdef+","+intnum);

上述程式碼中,先定義兩個變數intdef和intnum,前者用於儲存只設定最大範圍值是10的隨機數,後者用於儲存10~20間的隨機數;然後,將獲取的這兩個變數,通過瀏覽器的控制檯進行輸出。


注意:

在random()函式中,當指定的範圍值為10~20,也包含這兩個範圍本身,即函式也將返回10或20。

2.6.2 escape()和unescape()函式

esacpe()和unescape()是一對編碼和解碼函式,escape()函式功能是對指定的字串內容進行解碼,該函式返回一個編碼後的新字串;而unescape()函式則是對編碼後的新字串進行解碼,解碼後的字串為escape()函式編碼前的原始字元內容。接下來逐一進行介紹。


1.escape()函式

呼叫格式:

_.escape(string)

該函式的功能是:返回一串編碼後的新字串內容。引數string為編碼前的字串。

在使用escape()函式進行編碼時,被編碼的字串的字元有的被替換成了十六進位制的轉義序列,有的則被替換成一些常用的HTML程式碼。


2.unescape()函式

呼叫格式:

_.unescape(string)

該函式的功能是:將編碼後的字串進行解碼,返回字串編碼前的原始內容。引數string為已編碼的字串。示例如下。

var stresc = _.escape("111/163'haha'<hehe>&gaga-_.!~*")
var strunesc = _.unescape(stresc);
console.log("編碼後:"+stresc);
console.log("編碼前:"+strunesc);

在上述程式碼中,使用escape()函式對一串特殊的字串內容進行編碼,並將編碼後的新字串內容賦值給變數“stresc”;然後對已編碼字串呼叫unescape()函式進行解碼,並將解碼後的原始字串內容複製給變數“strunesc”;最後,通過瀏覽器的控制檯輸出這兩個變數的值。

從上圖中可以看出,escape()函式在編碼時不會對ASCII字母數字以及“-_.!~*”等特殊的字元進行編碼,它們只是原樣輸出,除此之外的字元將被轉移字元所替代。


2.6.3 template()函式

在Underscore庫中,template()是一個十分重要的函式,這個輕量級的函式可以幫助開發人員有效地組織頁面的結構和底層邏輯。該函式可以解析3種模板標籤,分別如下表所示。

template()函式模板標籤
模板標籤 功能描述
<% %> 標籤中包含的通常是JavaScript程式碼,在頁面渲染資料時被執行
<%= %> 標籤中包含的通常是變數名、函式名、物件屬性,執行時直接展現呼叫後的資料
<%- %> 標籤在輸出資料時,能將HTML標記轉成常用字串形式,以免程式碼的攻擊

template()函式的呼叫格式如下。

_.template(templateString,[data],[settings])

其中引數templateString就是模板標籤,可選引數data為渲染標籤的資料,可選引數settings為自定義模板標籤的字元格式,比如可以將<% %>修改為{% %}格式,接下來通過簡單的事例逐一進行介紹。

1.<% %>模板標籤

<% %>在template()函式使用時,在它包含處可以執行任意的JavaScript程式碼,同時允許在呼叫template()函式時使用物件屬性的方式傳遞引數值。示例如下。
var tpl = _.template("<%console.log(str)%>");
tpl({str:'姓名:皮卡丘'});
在上述程式碼中,首先使用<% %>模板標籤呼叫template()函式。在標籤中,將通過控制檯輸出指定的任意字元,然後執行tpl函式,執行時使用物件屬性的方式向標籤中的形參變數賦值。最終在Chrome瀏覽器的控制檯輸出。

2.<%= %>模板標籤
與<% %>模板標籤不同,<%= %>模板標籤可以直接顯示變數或函式的結果。它的功能是輸出資料,而不是執行。因此,如果想使用<%= %>模板標籤實現與上圖同樣的效果,程式碼修改如下。
var tpl = _.template("<%=str%>");
console.log(tpl({str:'姓名:皮卡丘'}));
上述程式碼中的tpl函式可以顯示傳入的任意字元內容,當在控制檯輸出該函式時候,其實效果和上圖一樣。


3.<%- %>模板標籤
<%- %>與<%= %>模板標籤的功能基本相同,不同之處在於,<%- %>模板標籤不僅可以輸出變數或函式的結果,而且可以將結果中的HTML程式碼轉成字元形式,以避免程式碼受到攻擊。如果希望只返回字串,使用<%- %>模板標籤是一個不錯的選擇。示例如下。
var tpl = _.template("<%-str%>");
console.log(tpl({str:"姓/'名'&:<皮>卡丘"}));
在上述程式碼的輸出結果中,新增一些任意的HTML格式程式碼,而當使用<%- %>模板標籤輸出這些內容時,其中的HTML程式碼會轉成轉義符。它的轉換標準與前面介紹的escape()函式一樣,只是針對部分HTML程式碼進行替換,並不是全部。最終在Chrome瀏覽器的控制檯輸出效果如上。


示例2-1  <script>模板標籤的使用

與上述三種模板標籤都不相同,<script>模板標籤是在HTML頁面中進行宣告的,宣告的標誌是將該標籤的type屬性值設定為“text/template”,即表示這是一個模板標籤。在模板標籤中,還可以新增<% %>和<%= %>標籤來組織和佈局頁面的結構,然後呼叫template()函式,通過ID號繫結<script>模板標籤,並將可選引數data的內容渲染到模板標籤中對應的物件屬性中,從而實現根據模板繫結資料的頁面效果。接下來通過一個示例進行詳細介紹。

1.功能描述
在頁面中,首先使用<script>標籤的方式自定義模板;然後建立一個資料來源,呼叫template()函式解析模板,並將資料來源填充至模板中並返回填充後的模版內容;最後將填充後的模板內容追加到頁面的渲染元素內,從而最終實現根據自定義模板展示資料的功能。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>template自定義模板</title>
<script src="../script/jquery-1.11.1.js"></script>
<script src="../script/underscore.js"></script>
<script src="../script/backbone.js"></script>
<style type="text/css">
   body{ font-size:13px;}
   ul{ list-style-type:none;
      padding:0px;margin:0px;width:360px }
   li:first-child span{ float:left;
      border-bottom:solid 1px #ccc;background-color:#eee; 
      font-weight:bold }
   ul li span{ width:80px;text-align:left;float:left; 
      padding:0px 5px;border-bottom:dashed 1px #ccc;line-height:28px;}
</style>
</head>
<body>
	<!--這段script是段模板程式碼 ,接收資料後並生成HTML程式碼 -->
	<script type="text/template" id="tpl">
		<%
			var intSumScore=0;
			var intAveScore=0;
			for(var i=0;i<list.length;i++){
				var item = list[i]
		%>
		<li>
			<span>
				<%=item.StuId%>
			</span>
			<span>
				<%=item.Name%>
			</span>
			<span>
				<%=item.Sex%>
			</span>
			<span>
				<%=item.Score%>
			</span>
		</li>
		<%
				intSumScore+=parseInt(item.Score);	
				intAveScore=intSumScore/list.length;	
			}
		%>
		<li>
			<span>平均分:</span>
			<span><%=intAveScore%></span>
			<span>總分:</span>
			<span><%=intSumScore%></span>
		</li>
	</script>
	<!-- 將上面模板程式碼生成的HTML程式碼新增到這段程式碼後面 -->
	<ul id="element">
		<li>	
			<span>學號</span>
			<span>姓名</span>
			<span>性別</span>
			<span>總分</span>
		</li>
	</ul>
	<script type="text/javascript">
		var ele = $("#element");
		var tpl = $("#tpl").html();
		var data = {
	        list: [
	            { StuId: 's0101', Name: '劉小明', Sex: '男', Score: '345' },
	            { StuId: 's0102', Name: '李清燕', Sex: '女', Score: '445' },
	            { StuId: 's0103', Name: '張二保', Sex: '男', Score: '355' },
	            { StuId: 's0104', Name: '陳明基', Sex: '男', Score: '564' },
	            { StuId: 's0105', Name: '舒明珠', Sex: '女', Score: '543' }
	        ]
	    };
		var html = _.template(tpl,data);
		ele.append(html);
	</script>
</body>
</html>
2.原始碼分析
HTML頁面程式碼由三部分組成:第一部分是<script>元素的模板標籤,第二部分是頁面中用於渲染填充資料的元素,第三部分是編寫JavaScript程式碼:建立資料、繫結模板、渲染資料。接下來我們逐一介紹。
(1)在<script>元素的模板標籤中,分別使用<% %>、<%= %>標籤來執行程式碼和顯示資料,在執行程式碼時,先定義了兩個變數,用於儲存資料中的總分數和平均分數值,然後使用for語句遍歷填充資料的陣列物件list。在遍歷過程中,使用<%= %>標籤直接顯示物件中的各項元素,同時計算總分數和平均分數值,最後將獲取的這兩項數值使用<%= %>標籤的方式直接顯示在<span>元素中。
(2)在頁面渲染元素ID為“element”的<ul>元素中,先新增一個<li>元素,用於填充資料的標題部分,全部的填充資料通過追加的方式新增至該元素中。
(3)在頁面的JavaScript程式碼部分,首先定義兩個變數ele和tpl,分別用於儲存頁面的渲染元素和模板內容;然後建立一個資料物件data,這個物件也可以通過請求服務端的資料介面進行返回;呼叫template()函式解析模板,並將建立的資料物件填充至模板中,同時,執行該函式後,返回一個資料填充至模版後的內容;最後,通過append()方法將該內容追加到頁面的渲染元素中,最終實現通過template()函式繫結並顯示的頁面效果。


2.6.4 chin()函式

在Underscore庫中,有一個作用與jQuery中鏈式寫法相似的函式,它就是chain(),呼叫該函式後,可以在程式碼中採用鏈式寫法,逐層獲取返回值。其呼叫格式如下。

_.chain(obj)

該函式的功能是:返回一個包裝後的物件,當再次呼叫該物件的方式時,將繼續返回該物件的另外屬性值,即可以逐層返回一個物件的多個屬性值。引數obj可以是一個陣列、集合、物件。示例如下。

var data = [1,2,3,4,5,6,7,8,9,10];
var find = _.chain(data)
			.filter(function(num){
				return num%2==0;
			})
			.without(data,2,10)
			.last()
			.value();
console.log("最終值為:"+find);


在上述程式碼中,先定義一個變數data,用於儲存陣列物件;然後呼叫chain()函式包裝這個陣列物件;最後採用鏈式寫法,根據每次的返回結果一次呼叫filter()、without()、last()、value()函式,而呼叫時各個物件的返回結果又不相同。接下來進行逐步分析。

1.當呼叫filter()函式時候,返回一個可以被2整除的陣列物件,也就是原始data陣列中的偶數部分,即[2,4,6,8,10]。

2.當呼叫without()函式時,將在返回的偶數陣列中,返回一個元素值除2和10之外的陣列,即[4,6,8]。

3.當呼叫last()函式時,將返回最新陣列物件中的最後一個元素項,即[8]。

4.當呼叫value()函式時,將直接返回陣列的元素值,即8。

因此,當通過console.log方法在控制檯輸出變數find內容時,其顯示內容為8。


注意:

在上述程式碼中value()也是一個很實用的函式,它的功能是獲取包裝物件的值,其呼叫格式如下:

_(obj).value()

在上述呼叫格式程式碼中,引數obj可以是任意的物件,包括集合、陣列等。


相關文章