《JavaScript編程精解》簡明讀書心得-下


這是《JavaScript編程精解》簡明讀書心得 的下半部分。這本書的下半節有兩章客戶端JavaScript內容。由於這部分內容比較繁雜,而概念比較簡單,而且很多工作都可以用JQuery來完成,所以我讀這本書的時候,這部分就直接瀏覽了一遍。因此這下半部分只有兩節內容,模塊化和正則表達式。

模塊化的JavaScript

比起C#中可以輕松地在類中聲明私有字段、繼承類、封裝接口、生成命名空間,JavaScript簡直太可憐了——它不提供任何模塊化的原生支持。事實上,我們只能通過一些JavaScript的特性來“模擬”出模塊的特點。模塊的特點是“封裝”,即模塊的使用者可以對模塊內的細節一無所知,其目的就是希望當其他模塊發生變化時,自身可以不變,增強了代碼的復用性。在JavaScript中,這是通過以下兩個特性來完成的:

  • 1、函數內部的局部變量對外不可見(閉包) 
  • 2、對象的字段只能通過對象調用(這好像又是廢話)

用函數封裝變量,使得不需要出現在全局作用域的變量不出現在全局作用域。比如我希望獲得一個計算圓柱體和圓錐體體積的函數,也許你會這樣做:

var PI = 3.1415926;
var circleArea = function(theCircle) { return theCircle.radius*theCircle.radius*PI; }
var cylinderVolume = function(theCylinder) {  return circleArea(theCylinder.circle)*theCylinder.height; }
var taperedVolume = function(theTapered) {  return circleArea(theTapered.circle)*theTapered.height/3; }

瀏覽器解釋完這4條語句之后,你獲得了想要的兩個函數cylinderVolume和taperedVolume,但是請注意,你也獲得了PI和circleArea,這並不是你想做的,換句話說,全局作用域被PI和circleArea“污染”了。也許前面一個腳本文件里已經定義了另一個PI=1.414,或者只有你掌握了計算圓面積的方法circleArea,你不想其他人也能方便地使用(話說回來既然用了JavaScript而不是什么COM技術,不管如何扭曲代碼你的秘密總會被解析出來的,因為源碼就是公開的嘛),你都應該將這兩個家伙封裝起來。下面的實現可能會比較好:

function createFunction(){
    var PI = 3.1415926;
    var circleArea = function(theCircle) { …… }
    var cylinderVolume = function(theCylinder) {  …… }
    var taperedVolume = function(theTapered) {  …… }
    window.cylinderVolume = cylinderVolume;
    window.taperedVolume = taperedVolume;
}
createFunction();

window是瀏覽器窗口對象,所有的“全局變量”都是window的屬性。這個函數運行之后,window對象只獲得了兩個計算圓柱體和圓錐體體積的函數,在后面代碼里可以方便地調用這兩個函數。你看,PI和circleArea並沒有隨着createFunction定義的結束而被釋放,它們被保存到一個由瀏覽器維護的地方,只要調用taperedVolume函數,就會使用到它們,這就是“閉包”的特性。

如果仔細考慮,上面的實現還有問題,那就是污染了變量createFunction,那么也許使用匿名函數會更好。下面是最好的實現:

function(){
    var PI = 3.1415926;
    var circleArea = function(theCircle) { …… }
    var cylinderVolume = function(theCylinder) {  …… }
    var taperedVolume = function(theTapered) {  …… }
    window.cylinderVolume = cylinderVolume;
    window.taperedVolume = taperedVolume;
}();

這樣,利用函數體內局部變量是不可達的這一特點,就完成了對模塊的封裝,cylinderVolume和taperedVolume就是對外交流的接口。 也許你會說,直接把PI值和計算圓面積的邏輯寫到計算體積的函數里不就行了?但是,當函數的規模足夠大的時候,你一定不會想那么做的。

至於利用對象的屬性封裝字段則很簡單了,因為對象(名值對)本身就是用來模擬面向對象語言中的“對象”的,通過對象名來訪問對象內部的屬性,這是理所當然的。

正則表達式

正則表達式提供了非常靈活的字符串匹配方法,可想而知在表單驗證之類的領域有着很強的應用。之前看犀牛書的時候一帶而過,這次看書雖然不指望完全掌握,但我總想還是稍微整理一下吧。

下面是正則表達式的一個簡單的應用,返回1表示能夠在索引(從0開始)為1的地方找到第一個匹配el。

var text = “hello”;
text.search(/el/);//->1

正則表達式以一個斜杠開頭,以一個斜杠結尾,中間的內容為匹配的內容。正則表達式可以通過通配符匹配字符串:

“1a 2 3d”.search(/\s\d\s/); //->3 匹配到a后面的“空格2空格”

還有一些常用通配符:

通配符 釋意
\d  任意數字
\w  任意單詞
\s  任意空字符:制表符、換行符、空格符
\b   單詞邊界:標點符號,空格,字符串開頭和結束
 .  任意不是換行符的字符

正則表達式中,中括號"["和"]"之間的部分表示符合任意字符的匹配,星號和加號分別表示可以重復任意次數和重復至少一次:

“abccxa”.search(/[xyz]/); //->4
“abccxa”.search(/c*xa/); //->4

字符串除了search方法,還有replace方法用以替換掉被匹配的字符串,還有match方法檢測是否找到匹配。

寫在最后的話

花了兩天看完這本小書,有一些收獲都基本寫到了這兩篇博文里面。也許有人會問:既然JavaScript有這么多缺點,OOP是模擬出來的,事件機制也是模擬出來的,甚至調用函數的時候連參數都不檢查,那為什么還要學習它呢?我有這樣的答案:首先,JavaScript的本質是簡單的,在這種簡單的基礎之上構造抽象問題的思想卻是值得學習的(當突然理解“閉包”的時候,我覺得設計者的思路真是妙絕了);其次,JavaScript作為一種“立竿見影”的語言,能幫助我做想做的事情:開發游戲——WebGL官方demo里面有個賽車游戲,簡直太COOL了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM