Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

JavaScript Advanced Skill

on

  • 2,306 views

Introduce some advanced skills of JavaScript

Introduce some advanced skills of JavaScript

Statistics

Views

Total Views
2,306
Views on SlideShare
2,304
Embed Views
2

Actions

Likes
0
Downloads
13
Comments
0

2 Embeds 2

http://www.linkedin.com 1
http://192.168.6.179:3030 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

JavaScript Advanced Skill JavaScript Advanced Skill Presentation Transcript

  • JavaScript 進階教學 by David JavaScript Advanced Skill by David Hung 2010-11-22
  • JavaScript的組成
    • 一般來說,JavaScript其實是由三個部份所組成:
      • ECMAScript
        • 定義核心的程式語言架構、變數型態等
      • DOM (Document Object Model)
        • 負責與頁面元素(element)溝通,例如修改元素的HTML內容
      • BOM (Browser Object Model)
        • 負責與Browser溝通,例如取得螢幕的寬高等
  • 觀念澄清
    • 在JavaScript裡可以multi-thread執行程式?
      • 不可以! JavaScript是一個single thread的語言,有一些JavaScript Library宣稱他們可以使程式碼跑起來像是multi-thread。其實是用setTimeout function來”模擬”multi-thread的行為而已,但實際上還是single thread。
      • ※ 在 Browser 裡有一個 Queue 用來處理所有要執行的程式區塊,利用 setTimeout 可以延後一個程式區塊的執行時間點。而讓 Browser 有時間先做其他的事。
    • 在JavaScript裡傳遞參數時,到底是pass by value還是pass by reference?
      • 全部都是pass by value。不過如果pass的參數型態為reference type(i.e. object, array...etc.)時,修改該物件裡的屬性值,仍會影響到原先的物件資料。
  • DOM Event Flow
    • 在JavaScript裡,Event的傳遞分為兩個階段:
      • Capture phase
        • target.addEventListener(type, listener, true);
      • Bubbling phase
        • target.addEventListener(type, listener, false);
  • 寫JavaScript的好習慣(Good Practice)
    • 一個function要碼都有return值(在不同condition時),要碼就都沒有。不要有時會return值,有時卻不會。容易造成混洧。
    function getShortBrowserName(obj) { if( obj.title == 'Firefox' ) { return 'FF'; } else if ( obj.title == 'Internet Explorer' ) { return 'IE'; } } 上面這段code不好的地方在於,如果傳入object的title屬性不為Firefox或Internet Explorer字串時,就不會return任何值。Call這個method的人就會接到undefined,而這可能不是預期中的事。
  • 寫JavaScript的好習慣(Good Practice)
    • 不要用with statement。因為它會造成執行效能降低,而且會增加debug時的困難。
    function updateBody() { with(document.body) { alert(tagName); innerHTML = 'Hello World'; } } with statement是用來縮減code的長度,可省略在statement裡面aceess宣告的object屬性值的前置字串。但使用with statement時,在執行code會多找一層scope導致效能變差。改用比較短的local varibable先將該object記起來是比較好的寫法,如下: function updateBody() { var body = document.body alert(body.tagName); body.innerHTML = 'Hello World'; }
  • 寫JavaScript的好習慣(Good Practice)
    • if – else裡的statement最好都要用括號括起來,即使只有一行。這樣可以增加程式碼的可讀性。
    • 每行statement最好都要有分號(;)結尾。雖然JavaScript允許每行的結尾可以沒有分號,但這樣之後若要做code壓縮(自動刪除空白和斷行)時,就會產生錯誤了。
    • 永遠不要用浮點數(floating number)來做compare比較。因為浮點數在JavaScript裡是有誤差值的。
    • 若要將一個字串(string)變數轉為數字(number)型態時,最好是用parseInt或parseFloat作轉換。若是其他資料型態(data type),則使用Number() casting function。
  • 寫JavaScript的好習慣(Good Practice)
    • 透過在function裡的arguments物件,可以模擬類似其他程式語言(如: Java)的多形(Polymorphism)function。在處理時,可以根據傳入不同的參數型態或數量做不同的處理變化。
    // 加總函式 function sum() { var total = 0; for( var i=0; i<arguments.length; i++ ) { total += arguments[i]; } return total; } // 測試 code log( sum() ); // 0 log( sum(1, 2) ); // 3 log( sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ); // 55
  • 寫JavaScript的好習慣(Good Practice)
    • 宣告一個變數時記得前面一定要加var。雖然不加var也是JavaScript可接受的寫法(會變成global variable),但是這樣容易造成混洧和發生錯誤。
    • 儘量避免明示宣告一個primitive wrapped object(String, Boolean, Number,例: var str = new String(‘test…’);)。因為這會讓開發者搞不清楚他們是在處理reference value or primitive value,容易造成混洧。
  • 寫JavaScript的好習慣(Good Practice)
    • 在一個遞迴(recursive)或匿名(anonymous)函式裡,最好使用arguments.callee代替指定function name。這樣一來,日後即使換了function name(reference),也不用跟著調整function code裡面寫到的名稱。
    // a recursive function function grabData() { if( storage.length > 0 ) { // storage is a array var obj = storage.shift(); // your handle code here var method = arguments.callee; window.setTimeout(function() { method(); // execute grabData method actually }, 300); } }
  • 寫JavaScript的好習慣(Good Practice)
    • 在使用Closure (a anonymous function inside another function)時,只有在真正需要用到時才用這個寫法,別過度使用它。因為它會保留上層function的整個scope,造成額外的記憶體消耗。
    • 儘用少用setInterval,因為它有可能會讓一段code還沒結束前就開始執行下一次的程序。可以改用setTimeout加上遞迴(recursive)寫法來達成與setInterval一樣的效果,這樣可保證每次執行code時,上一次程序已經執行結束。
    • 如果要用JavaScript判斷不同瀏覽器或Capability來做例外處理,最好當成是一般解法無法運作時的最後手段。非不得已才用這個方式。
  • 寫JavaScript的好習慣(Good Practice)
    • 不要過度頻繁的操作element的innerText或innerHTML,因為這會降低執行速度,比較沒效率。如果有個迴圈會連續對某個element改寫這兩個properties值,最好先將HTML或文字寫在string buffer裡,然後只做一次改寫的動作。
    // 原本的寫法,比較沒效率,做了 100 次 DOM Element 操作 var panel = document.getElementById('my_panel'); for( var i=0; i<100; i++ ) { var item = document.createElement('div'); item.innerHTML = 'Item-'+i; panel.appendChild(item); } // 改用 String Buffer 的寫法,只做一次 DOM Element 操作 var panel = document.getElementById('my_panel'); var html = ''; for( var i=0; i<100; i++ ) { html += '<div>Item-'+i+'</div>'; } panel.innerHTML = html;
  • 寫JavaScript的好習慣(Good Practice)
    • 當使用指定innerHTML來改變一個element時,寫code時最好不要將其element的children綁定event handler。如果element的children已經有綁定event handler,最好手動將綁定的event handler移除掉(例: targetElm.onclick = null;),避免memory leak發生(尤其在IE)。
    • 當要寫一段判斷式時(if, while…etc.),最好總是確保括號裡的陳述是一個Boolean值。例如要判斷一個變數是否為一個字串才做處理,最好寫成 if( typeof str == ’string’ ) ,而不要寫成 if( str )。後者雖然也可work(因變數原格式會被自動轉成Boolean格式),但檢查條件鬆散許多,較容易發生不該出現的狀況。
  • 寫JavaScript的好習慣(Good Practice)
    • 儘量減少event handler(function)的數量,因為綁定越多的handler會消耗更多memory,而降低執行效率。可以使用” Event Delegation “的技巧來減少event handler的數量。
    // Event Delegation Sample document.onclick = function(event){ //IE doesn't pass in the event object event = event || window.event; //IE uses srcElement as the target var target = event.target || event.srcElement; switch(target.id){ case &quot;help-btn&quot;: openHelp(); break; case &quot;save-btn&quot;: saveDocument(); break; case &quot;undo-btn&quot;: undoChanges(); break; //others? } };
  • 寫JavaScript的好習慣(Good Practice)
    • JavaScript與CSS、HTML彼此之間應該儘量減少耦合(coupling)程度。HTML負責提供內容(content),CSS專職呈現(appearance),JavaScript則處理行為(behavior) 。意即: 在HTML裡不該出現JavaScript及CSS style的code,在JavaScript裡不該去處理CSS style及HTML tag。過度的耦合會造成code maintain上的困難。
  • 寫JavaScript的好習慣(Good Practice)
    • 當一段程式邏輯需要耗費大量時間運算時,可以試著將可分割的程式區塊切成數小段,用setTimeout指定一小段時間間隔後再執行。這樣可以讓頁面有更多喘息的時間來回應使用者的操作行為,而有更好的使用者互動經驗。
    // 原本的寫法 function insertItem() { var panel = document.getElementById('my_panel'); for( var i=0; i<100; i++ ) { var item = document.createElement('div'); item.innerHTML = 'Item-'+i; item.onmouseover = function() { this.style['background'] = 'gold'; }; item.onmouseout = function() { this.style['background'] = 'transparent'; }; // ... other handle codes panel.appendChild(item); } } // 新的寫法 var count = 0; function insertItem(index) { if( index >= 100 ) return; var panel = document.getElementById('my_panel'); var item = document.createElement('div'); item.innerHTML = 'Item-'+index; item.onmouseover = function() { this.style['background'] = 'gold'; }; item.onmouseout = function() { this.style['background'] = 'transparent'; }; // ... other handle codes panel.appendChild(item); // delay a while to let browser take a break var method = arguments.callee; window.setTimeout(function() { method(count++); }, 50); }
  • 寫JavaScript的好習慣(Good Practice)
    • 將Event Handler裡面的商業邏輯獨立出來。Event Handler應該只處理與Event有關資料,例如抓取keyPress event的keyCode或event target。若要利用這些值做一些處理,則改在別的function裡做。不要pass event object到Event Handler以外的地方。
    // 原本的 code function handleKeypress(event) { if( event.keyCode == 13 ) { var target = EventUtil.getTarget(event); var value = 5 * parseInt(target.value); if( value > 10 ) { var elm = document. getElementById('error-msg'); elm.style.display = 'block'; } } } // 改寫後的 code ,將商業邏輯獨立出來 function validateValue(value) { value = 5 * parseInt(value); if( value > 10 ) { var elm = document .getElementById('error-msg'); elm.style.display = 'block'; } } function handleKeypress(event) { if( event.keyCode == 13 ) { var target = EventUtil.getTarget(event); validateValue(target.value); } }
  • 寫JavaScript的好習慣(Good Practice)
    • 儘量減少access global variable的次數可以增進效能,因為減少了traverse time。如果一個function裡有數個地方會access同一個global variable(如: document),可以先用一個local variable去指向global variable,後續的code再access local variable,這樣可加快速度。
    // 原本的 code function updateUI() { var imgs = document .getElementsByTagName('img'); for( var i=0, len=imgs.length; i<len, i++ ) { imgs[i].title = document.title + 'image' + i; } var msg = document.getElementById('msg'); msg.innerHTML = 'Update complete'; } // 改寫後的 code ,先宣告一個 local variable 去記 // document function updateUI() { var doc = document; var imgs = doc.getElementsByTagName('img'); for( var i=0, len=imgs.length; i<len, i++ ) { imgs[i].title = doc.title + 'image' + i; } var msg = doc.getElementById('msg'); msg.innerHTML = 'Update complete'; }
  • 寫JavaScript的好習慣(Good Practice)
    • 如果要建立一個Storage來存放資料時,用Array會比Object快。在Access資料的速度上,前者的複雜度為O(1),後者為O(n)。
    • 若一段code有很多if-else時,改採用switch寫法執行速度會比較快一些。另外可以將比較容易match到的case條件排在比較上面,比較少match到的case排在下面,也會讓效能上有些許提昇。
  • 寫JavaScript的好習慣(Good Practice)
    • 儘量減少對DOM的操作會使效能有非常顯著的提升,DOM的運算是Browser裡最耗運算資源的。當要對一個HTML element連續插入很多或複雜的child element時,可以用DocumentFragment先將整個DOM結構建立好,再一次加進element,速度會快很多!
    // 原本的寫法 function insertItem() { var panel = document.getElementById('my_panel'); for( var i=0; i<100; i++ ) { var item = document.createElement('div'); item.innerHTML = 'Item-'+i; item.onmouseover = function() { this.style['background'] = 'gold'; }; item.onmouseout = function() { this.style['background'] = 'transparent'; }; // ... other handle codes panel.appendChild(item); } } // 改寫後的 code ,將 item 寫進 DocumentFragment function insertItem() { var panel = document.getElementById('my_panel'); var fragment = document .createDocumentFragment(); for( var i=0; i<100; i++ ) { var item = document.createElement('div'); item.innerHTML = 'Item-'+i; item.onmouseover = function() { this.style['background'] = 'gold'; }; item.onmouseout = function() { this.style['background'] = 'transparent'; }; fragment.appendChild(item); // ... other handle codes } panel.appendChild(fragment); }
  • Naming Rule
    • Variable請用小寫名詞,如: person, card。
    • Function請用小寫動詞開頭,如: getName(), pushEvent()。假如Function會回傳一個Boolean值,請用is開頭,如: isEnabled(), isVisible()。
    • Constant請用大寫及底線,如: STATE, EVENT_TYPE。
    • 如果是private使用,可以在Variable及Function字首加上底線。如: _target, _getElement()。
    • HTML Element的class name、寫入Cookie或發送HTTP Request的參數名稱請用底線'_'區隔單字。如: 'window_panel', 'personal_setting', 'widget_position'。
  • Convention Rule
    • 在JavaScript裡,字串用單引號標示,在HTML裡用雙引號標示。當規則定下來之後,如果有一天需要把HTML element改由JavaScript動態產生,就可以直接覆製HTML code到JavaScript字串變數裡,不需再擔心單雙引號相衝的問題。
    • 縮排Tab改用空白取代。這是為了防止當很多人一起改code時,程式碼會因為每個人的編輯器不同,Tab所表示的空白字元數不同,而導致程式碼縮排不一致變的亂七八糟。
    // in JavaScript var str = 'Hello World' ; // in HTML <div class= “err-msg“ ></div> // 假如必須要在 JavaScript 裡直接寫 HTML code var html = '<div class=“err-msg“></div>' ;
  • 利用Ant將JavaScript及CSS檔案串接
    • 介紹文章: http://www.julienlecomte.net/blog/2007/09/16/
      • 好處: 將多個JavaScript或CSS檔案串接成為一個檔案後,可以減少Browser透過網路戴入的次數(requests)。進而加快頁面的瀏覽速度。使用此方法串接js檔案時,需注意先後順序,如同<script> import js file一般。
    <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <project basedir=&quot;.&quot; default=&quot;js.concatenate&quot; name=&quot;JS Concatenation&quot;> <!-- the directory to output to --> <property name=&quot;build.dir&quot; value=&quot;./js&quot; /> <!-- the directory containing the source files --> <property name=&quot;src.dir&quot; value=&quot;./dev/src&quot; /> <!-- Target to concatenate all js files --> <target name=&quot;js.concatenate&quot;> <concat destfile=&quot;${build.dir}/concatenated/all.js&quot;> <filelist dir=&quot;${src.dir}/js&quot; files=&quot;a.js, b.js&quot;/> <fileset dir=&quot;${src.dir}/js&quot; includes=&quot;**/*.js&quot; excludes=&quot;a.js, b.js&quot;/> </concat> </target> </project>
  • 其他資源
    • Debuger
      • Firebug
    • Compressor
      • JSMin
      • YUI Compressor
    • Validator
      • JSLint
    • Framework
      • http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks
  • JavaScript推薦書籍
    • Professional JavaScript for Web Developers, 2/e
    • JavaScript: The Good Parts
    • Pro JavaScript Design Patterns
  • Tha Thank You!!