【讀書筆記】讀《JavaScript高級程序設計-第2版》 - 非函數部分

章節列表:css

第08章:BOM
第09章:客戶端檢測
第10章:DOM
第11章:DOM2和DOM3
第12章:事件
第13章:表單腳本
第14章:錯誤處理與調試
第17章:Ajax和JSON
第20章:最佳實踐

片斷串接:html

  1 (function($){
  2      
  3      /**
  4       * 第8章:BOM
  5       * window對象的核心函數
  6       * 1>超時調用和間歇調用
  7       * 2>核心對象:
  8       *     a>location
  9       *     b>navigator
 10       *     c>screen
 11       *     d>history
 12       */
 13      //超時調用和間歇調用
 14      (function(){
 15          window.setTimeout('alert("hello world!")', 1000);        //不推薦傳遞字符串
 16          var timeoutId = window.setTimeout(function(){            //推薦方式
 17              alert('hello world!');
 18          }, 5000);
 19          //只要在指定的事件還沒有過去以前調用clearTimeout(),就能夠徹底取消超時調用
 20          //有時,沒有必要跟蹤超時調用ID,由於每次執行代碼以後,若是再也不設置另外一次超時調用,調用就會自行中止
 21          clearTimeout(timeoutId);
 22          //間歇調用,間歇調用的ID咱們通常是須要跟蹤的
 23          var intervalId = setInterval(function(){
 24              alert('hello world!');
 25          }, 1000);
 26          clearInterval(intervalId);
 27      })();
 28      
 29      /**
 30       * 第9章:客戶端檢測
 31       * 能力檢測:在編寫代碼以前先檢測特定瀏覽器的能力。
 32       * 怪癖檢測:檢測瀏覽器實現中的bug。
 33       * 用戶代理檢測:經過檢測用戶代理字符串來識別瀏覽器。用戶代理字符串中包含大量與瀏覽器相關的信息,包括瀏覽器、平臺、操做系統及瀏覽器版本。
 34       */
 35      
 36      /**
 37       * 第10章:DOM
 38       * 節點層次:類型(Document類型、Element類型、Text類型、Attr類型等等)、關係、操做。
 39       * DOM1級主要定義的是HTML和XML文檔的底層結構
 40       * 1>節點層次
 41       *     a>Node類型:文檔節點、元素節點、屬性節點、文本節點、註釋節點等等。
 42       *           i>節點名字nodeName和節點值nodeValue
 43       *          ii>節點關係
 44       *         iii>操做節點
 45       *     b>文檔節點Document
 46       *         i>文檔子節點<html>: var html = document.documentElement;
 47       *         ii>文檔信息:title、URL、domain、referrer
 48       *         iii>查找元素
 49       *         iv>特殊集合
 50       *         v>DOM一致性檢測
 51       *     c>元素節點Element
 52       *     d>文本節點Text
 53       */
 54      //DOM1
 55      (function(){
 56          var ele = document.getElementById('container');
 57          
 58          //注意:Node.ELEMENT_NODE在IE中是無效的
 59          console.log(ele.nodeType === Node.ELEMENT_NODE);
 60          
 61          //適用於全部瀏覽器
 62          if (ele.nodeType === 1) {
 63              console.log('element node');
 64              console.log(ele.nodeName);
 65              console.log(ele.nodeValue);
 66          }
 67          
 68          //節點的關係
 69          //document對象是window對象的一個屬性,能夠把其當作全局對象來訪問
 70          console.log(window.document);                      //HTMLDocument(#document)——對象
 71          console.log(window.document.documentElement);      //HTMLHtmlElement
 72          
 73          var html = document.documentElement;
 74          console.log(html === document.firstChild);         //true
 75          console.log(html === document.childNodes[0]);      //true
 76          
 77          document.title = 'xxxxxx';
 78      })();
 79      
 80      /**
 81       * 第11章:DOM2和DOM3
 82       * 元素大小:
 83       *     1>偏移量:offset系列(offsetLeft,offsetTop,offsetWidth,offsetHeight)
 84       *     2>客戶區:client系列(clientWidth,clientHeight)
 85       *     3>滾動條:scroll系列(scrollLeft,srollTop,scrollWidth,scrollHeight)
 86       * DOM遍歷
 87       * DOM範圍
 88       */
 89      
 90      /**
 91       * 第12章:事件
 92       * ------------------------------第一部分-----------------------------------
 93       * 1>每一個元素都有本身的事件處理程序屬性,將這種屬性的值設置爲一個函數,就能夠指定事件處理程序。
 94       * 2>使用DOM0級方法指定的事件處理程序被認爲是元素的方法。
 95       *     所以,這時候的事件處理程序是在元素的做用域中運行;換句話說,程序中的this引用當前元素。
 96       *     var btn = document.getElementById('myBtn');
 97       *     btn.onclick = function () {...}
 98       *     以這種方式添加的事件處理程序會在事件流的冒泡階段被處理。
 99       *     刪除DOM0級事件處理程序的方法是將對應事件處理程序屬性的值賦值爲null
100       * 3>DOM2級事件
101       *     btn.addEventListener('click', function(){...}, false);
102       *     btn.removeEventListener('click', handler, false);
103       *     false表示冒泡階段,true表示捕獲階段
104       * 4>IE事件處理程序attachEvent()和detachEvent()。
105       * 
106       * ------------------------------第二部分------------------------------------
107       * 1>事件處理程序數量直接會影響到頁面的總體性能:
108       *     a>事件處理函數佔用內存
109       *     b>必須事先指定全部事件處理程序而致使的DOM訪問次數,會延遲整個頁面的交互就緒時間。
110       * 2>由此,啓用事件委託:
111       *     a>什麼狀況下用?
112       *     b>優點在哪兒?
113       * 3>爲document對象添加事件處理程序
114       *     a>分析與傳統的事件處理程序設置相比的優點
115       * 4>每當將事件處理程序指定給元素時,運行中的瀏覽器代碼與支持頁面交互的JavaScript代碼之間就會創建一個鏈接。
116       *     所以,限制創建的鏈接數量是提升性能的方式,可採用事件委託。
117       *     另外,在不須要的時候移除事件處理程序,也是提升性能的方法。
118       * 5>模擬事件
119       *     var myEvent = document.createEvent("MouseEvents");
120       *    myEvent.initEvent("click", false, false);
121       *    elm.dispatchEvent(myEvent);
122       * 6>事件冒泡:
123       *     沒法冒泡的事件:blur、focus、load、unload
124       * 
125       */
126      //jquery事件綁定
127      (function(){
128          
129          //最開始的方法
130          //最新的jQuery中bind目前其實最後也是調用on()方法來實現的,
131          //因此呢,若是如今你們使用最新jQuery版本(目前爲1.7.1)的話,儘可能避免使用bind()方法。
132          $('.scv').bind('click', function(){
133              $('#container').append('<img class="scv" src="sth-bg.jpg" alt="鹿鼎記" />');
134          });
135          
136          //克隆方法
137          $('.scv').bind('click', function(){
138              $(this).clone(true).insertAfter(this);
139          });
140          
141          //live方法
142          //在最新的jQuery版本中,咱們最好不要使用live()方法,由於它已經被放棄了
143          $('.scv').live('click', function(){
144              $(this).clone(false).appendTo('#container');
145          })
146          
147          //咱們使用#container做爲綁定的上下文,jQuery將會在#container這個元素中查詢.scv元素
148          $('.scv', '#container').live('click', function(){
149              $(this).clone(false).appendTo('#container');
150          })
151          
152          //在最新的jQuery版本中,咱們最好不要使用live()方法,由於它已經被放棄了,
153          //這裏咱們使用delegate方法來指定事件綁定的上下文
154          $('#container').delegate('.scv', 'click', function(){
155              $(this).clone(false).appendTo('#container');
156          })
157          
158          //其實在最新版本的jQuery類庫中,全部以上方法在後面其實都是調用on()方法
159          $('.scv').on('click', function(){
160              $(this).clone(true).appendTo('#container');
161          });
162      
163      })();
164  
165      //事件冒泡和默認事件
166      (function(){
167          
168          $("body").click(function(){
169              alert("body")
170          })
171          
172          $('a').click(function(){
173              alert("xxxxx");
174              
175              //阻止事件傳播
176              event.stopPropagation();                  //ie很差使
177              window.event.cancelBubble = true;         //全都好使
178      
179              //阻止默認事件
180              window.event.returnValue = false;         //全都好使
181              window.event.preventDefault();            //ie很差使
182              
183              return false;                             //在jquery環境下,此句代碼既可以阻止瀏覽器默認事件,也可以阻止事件冒泡
184          })
185          
186          
187          var a = document.getElementsByTagName('a')[0];
188          
189          a.onclick = function(){
190              alert('a element');
191              
192              event.stopPropagation();                   //ie很差使
193              window.event.cancelBubble = true;          //全都好使
194              
195              //阻止默認事件
196              window.event.preventDefault();             //IE下很差使
197              window.event.returnValue = false;          //全都好使
198              
199              return false;                              //原生js下,這句代碼沒法阻止事件冒泡
200                                                         //但可以阻止瀏覽器的默認事件
201          }
202          
203      })();
204      
205      /**
206       * 第13章:表單腳本
207       */
208      (function(){
209          //取得表單
210          var myForm = document.forms[0];               //第一個表單
211          
212          console.log(myForm.elements.length);          //表單項:2
213          
214          myForm.elements[0].select();                  //聚焦並選中文本
215          
216      })();
217      
218      /**
219       * 第14章:錯誤處理與調試
220       * IE:工具——>Internet選項——>高級——>瀏覽下.顯示每一個腳本的錯誤通知
221       */
222      (function(){
223          try {
224              window.king();
225          } catch (error) {
226              alert(error.message);
227          } finally {
228              alert('haha');        //只要代碼中包含finally子句,那麼不管try仍是catch語句塊中的return語句都將被忽略。
229                                    //所以,在使用finally子句以前,必定要很是清楚你想讓代碼怎麼樣
230          }
231      })();
232      
233      /**
234       * 第17章:Ajax和JSON
235       */
236      (function(){
237          var obj1 = eval('{}');        //會把{}當作js處理,並未將其賦值,因此拋出錯誤
238          var obj2 = eval('({})');      //()在js中是一個表達式,沒有問題
239          var jsonText = '{}';
240          var obj3 = eval('(' + jsonText + ')');
241          
242          var jsonText1 = '{"name":"king","age":28,"author":true}';        //在json字符串中,其屬性必須用引號括起來
243          var people = JSON.parse(jsonText1, function(key, value){
244              switch (key) {
245                  case 'age':        return value + 1;
246                  case 'author':    return undefined;
247                  default:        return value;
248              }
249          });
250          console.log(people.age);
251          console.log(people.author);
252          
253          var json = '[1, 2, (function(){\
254              alert("xxxxx");\
255          })(), 4, 5]';
256          
257          var array = eval(json);            //具備不安全性
258          var array = JSON.parse(json);      //可以過濾惡意腳本
259          array[2];
260          
261      })();
262      
263      /**
264      * 第20章:最佳實踐
265      * 
266      * 1>可維護性
267      *     (1)定義
268      *         a>可理解性
269      *         b>直觀性
270      *         c>可適應性
271      *         d>可擴展性
272      *         e>可調試性
273      *     (2)代碼約定:
274      *         a>縮進、註釋
275      *             註釋在什麼地方:函數和方法、大段代碼、複雜的算法、Hack
276      *         b>變量和函數命名
277      *            小寫駝峯、合乎邏輯(如布爾型:is開頭) 
278      *         c>變量類型透明
279      *             初始化指定:var found = false;
280      *             匈牙利標記法:var bFound;("b"表明布爾型...)
281      *             指定類型註釋:var found /*:Boolean*/ = false;
282      * 2>鬆散耦合
283      *     (1)解耦HTML/JavaScript
284      *         i>從HTML角度
285      *             a>避免內聯代碼的<script>元素
286      *             b>避免使用HTML屬性來分配事件處理程序
287      *         ii>從JavaScript角度——避免在JavaScript中建立大量HTML
288      *             a>頁面中直接包含並隱藏對應HTML,在頁面渲染以後,再用JavaScript顯示該標記
289      *             b>進行Ajax請求獲取更多要顯示更多HTML
290      *     (2)解耦CSS/JavaScript
291      *         i>從JavaScript角度
292      *             避免直接更改樣式,而採用動態更改樣式類
293      *         ii>從CSS角度
294      *             避免使用css表達式
295      *     (3)解耦應用邏輯/事件處理程序
296      *         從事件處理程序中分離應用邏輯,有如下3點原則
297      *         i>勿將event對象傳給其餘方法;只傳來自event對象中所需的數據;
298      *         ii>任何能夠在應用層面的動做都應該能夠再不執行任何事件處理程序的狀況下進行;
299      *         iii>任何事件處理程序都應該處理事件,而後將處理轉交給應用邏輯。
300      * 3>編程實踐
301      *     (1)尊重對象全部權
302      *         永遠不修改不是由本身所擁有的對象
303      *     (2)避免全局量
304      *         推薦最多一個全局變量,讓其餘對象和函數存在其中
305      *         引入命名空間:將功能組合在一塊兒的單一的全局量的延伸。
306      *     (3)避免與null進行比較
307      *         i>若是值應爲一個引用類型,使用instanceof操做符檢查其構造函數
308      *         ii>若是值爲一個基本類型
309      *         iii>若是是但願對象包含某個特定的方法名,則使用typeof操做符確保指定名字的方法存在於對象上。
310      *     (4)使用常量
311      *         i>重複值——任何在多處用到的值都應抽取爲一個常量。
312      *         ii>用戶界面字符串——任何用於顯示給用戶的字符串,都應被抽取出來以方便國際化。
313      *         iii>URLs——在Web應用中,資源位置很容易變動,因此推薦用一個公共地方存放全部的URL。
314      *         iv>任何可能會更改的值——每當在用到字面量值的時候,都要問一下本身這個值在將來是否是會變化。
315      *            若是答案是"是",那麼這個值就應該被提取出來做爲一個常量。
316      * 4>性能
317      *    (1)注意做用域——將在一個函數中會用到屢次的全局對象存儲爲局部變量。
318      *    (2)選擇正確的方法
319      *         i>避免沒必要要的屬性查找
320      *             O(1):無論有多少值,執行的時間都是恆定的。通常表示簡單值和存儲在變量中的值。
321      *             O(n):總執行時間和值的數量直接相關。
322      *             使用字面量、變量和數組要比訪問對象上的屬性更有效率,由於後者是O(n)操做。
323      *             通常來說,只要能減小算法的複雜度,就要儘量減小。儘量多地使用局部變量將屬性查找替換爲值查找。
324      *         ii>避免雙重解釋
325      *             //某些代碼求值——避免
326      *             eval("alert('hello world')");        //用:alert('hello world');
327      *             //建立新函數——避免
328      *             var sayHi = new Function("alert('hello world')");    
329      *             //用:var sayHI = function(){alert('hello world');}
330      *             //設置超時——避免
331      *             setTimeout("alert('hello world')", 500);
332      *             用:serTimeout(function(){alert('hello world');}, 500)}
333      *             這些例子中都要解析包含了JavaScript代碼的字符串。這個操做時不能在初始的解析過程當中完成的,
334      *             由於代碼是包含在字符串中的,也就是說在JavaScript代碼運行的同時必須新啓動一個解析器來解析新的代碼。
335      *             實例化一個新的解析器有不容忽視的開銷,因此這種代碼要比直接解析慢得多。
336      *         iii>其餘方面
337      *             a>原生方法較快
338      *             b>switch語句較快
339      *             c>位運算較快
340      *     (3)最小化語句
341      *         i>多個變量聲明轉變爲單變量聲明
342      *         ii>插入迭代值
343      *             如:var name = values[i];
344      *                 i++;
345      *                 轉換爲:
346      *                 var name = values[i++];
347      *         ii>使用數組和對象字面量
348      *             如:var values = new Array();
349      *                 values[0] = 123;
350      *                 values[1] = 456;
351      *                 values[2] = 789;                //用4個語句建立和初始化數組——浪費
352      *                 轉換爲:
353      *                 var values = [123, 456, 789];    //只用一條語句建立和初始化數組
354      *     (4)優化DOM交互
355      *         i>最小化現場更新
356      *             不論是怎樣的一個DOM操做,對其都有一個性能懲罰,由於瀏覽器要從新計算無數尺寸以進行更新。
357      *             所以,完成一個操做所需的現場更新越少,代碼就越快。
358      *             一旦須要更新DOM,請考慮使用文檔碎片來構建DOM結構,而後再將其添加到現存的文檔中。
359      *         ii>使用innerHTML
360      *             而不用createElement()或appendChild()之類的DOM方法。
361      *         iii>使用事件代理
362      *             事件處理程序的數量和頁面響應用戶交互的速度之間有個負相關。爲了減輕這種懲罰,最好使用事件代理。
363      *         iv>注意NodeList
364      *             任什麼時候候要訪問NodeList,無論它是一個屬性仍是一個方法,都是在文檔上進行一個查詢,這個查詢開銷很昂貴。
365      *             var images = document.getElementsByTagName('img');        //生成的是一個NodeList
366      *             for (var i = 0, len = images.length; i < len; i++) {    //只調用了一次NodeList的length屬性
367      *                 var image = images[i];                                //避免在循環體內屢次調用NodeList
368      *             }
369      *             如下狀況會返回NodeList對象:
370      *             a>進行了對getElementsByTagName()的調用
371      *             b>獲取了元素的childNodes屬性
372      *             c>獲取了元素的attributes屬性
373      *             d>訪問了特殊的集合,如documents.forms、document.images等
374      *     (5)部署
375      *         i>構建過程——合併JavaScript文件(Ant等)
376      *             保存原有代碼的邏輯結構,最好避免使用一個文件存放全部的JavaScript,遵循面嚮對象語言中的典型模式:
377      *             將每一個對象或自定義類型分別放入其單獨的文件中。這樣能夠確保每一個文件包含最少許的代碼,使其在不引入錯誤的狀況下更容易修改。
378      *             要行進部署的時候,將這些源代碼合併爲一個或幾個歸併文件。
379      *         ii>驗證——JSLint
380      *         iii>壓縮
381      *             a>文件壓縮——如YUI壓縮器
382      *                 代碼長度——壓縮內容包括:刪除額外的空白(包括換行)、刪除全部註釋、縮短變量名。
383      *             b>HTTP壓縮
384      *                 配重指的是實際從服務器傳送到瀏覽器的字節數——
385      *                 在服務器端壓縮JavaScript文件,傳輸的字節數量大大減小,再由瀏覽器端解壓縮。
386      *             
387      */
388      
389 })(jQuery)
相關文章
相關標籤/搜索