Javascript 高級程序設計--總結【四】

*******************************  Chapter 11 DOM擴展  *******************************css

主要的擴展是 選擇符API 和 HTML5html

 

選擇符API:node

         document.querySelector('.img');web

         document.querySelector('#test');算法

 

         document.querySelectorAll('a');chrome

         //這個方式瀏覽器支持不多,返回是否能夠查詢獲得的結果編程

         document.matchesSelector('a.test');//true/falsecanvas

 

元素遍歷:跨域

         //這種方式就不會考慮後臺元素的 空白文本節點了,數組

         //由於使用 childNodes\firstChild\lastChild 不一樣的瀏覽器效果不同

         function eleAll(ele){

                   var child=ele.firstElementChild;

                   while(child!=ele.lastElementChild){

                            //do

                            child=ele.nextElementSibling;

                   }

         }

 

HTML5:

         與類相關的擴充:

                   //IE9+

                   document.getElementsByClassName('p');//返回NodeList

                   //獲取元素的 class ,返回字符串

                   div.className;//'cls '

 

 

                   //類的數組  Firefox 和Chrome 支持classList

                   div.classList;//['cls']

                   div.classList.remove('cls');

                   div.classList.add('newcls');

                   div.classList.toggle('cls');

                   div.classList.contains('cls');

         焦點管理:

                   document.activeElement;//返回獲取到焦點的元素

                   ele.hasFocus();//是否獲取到焦點

 

         HTMLDocument 的變化:

                   readyState:

                            document.readyState;//loading\complete

                   compatMode:

                            兼容模式:CSS1Compat(標準模式)、BackCompat(混雜模式)

                            document.compatMode;//CSS1Compat

                   head: Chrome 和 Safari 5

                            var head = document.head || document.getElementsByTagName('head')[0];

         字符集屬性:

                   document.charset;//"UTF-8"

                   document.defaultCharset;//默認操做系統設置,通常少有瀏覽器支持

 

         自定義數據屬性:

                   使用前綴 data-

                   dataset 獲取自定義屬性

                   Firefox\chrome\IE11+ 支持

                            <div id='divtest' data-appid='test'></div>

 

                            var div = document.getElementById('divtest');

                            console.log(div.dataset.appid);

                            //自定義設置 data-test

                            div.dataset.test='hah';

                            console.log(div.dataset.test);

 

         插入標記:

                   //大多數瀏覽器不支持的寫法,IE8以及以前能夠執行,可是腳本<script> 以前必須有 ‘做用域元素’

                   div.innerHTML='_<script>alert(1);<\/script>';

 

                   IE8的支持 window.toStaticHTML():

                            var text = '<a href="#" onclick="alert(1);">test</a>';

                            text = window.toStatocHTML(text);

                            console.log(text);//<a href="#">test</a>

 

                   //使用新的html 元素替換掉div 元素

                   div.outerHTML='<p>1232323</p>';        

 

                   insertAdjacentHTML():

                            div.insertAdjacentHTML('beforebegin','<p>1111</p>');// div以前同輩元素

                            div.insertAdjacentHTML('afterbegin','<p>2222</p>');// div 子元素第一個

                            div.insertAdjacentHTML('beforeend','<p>3333</p>');//  div 子元素最後一個

                            div.insertAdjacentHTML('afterend','<p>4444</p>');//  div 以後的同輩節點

                   內存與性能問題:

                            使用innerHTML\outerHTML\insertAdjacentHTML 刪除元素時候,元素以前綁定的事件關係並無刪除,會佔用內存    

         scrollIntoView:                 

                   div.scrollIntoView();

 

專有擴展:

         文檔模式:

                  

         <meta http-equiv="X-UA-Compatible" content="IE=Edge" />

    <meta http-equiv="X-UA-Compatible" content="IE=7" />

    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

        alert(document.documentMode);//返回IE 文檔模式版本號  五、六、七、八、九、11

        

         children:

                   ele.children;//只包含元素節點,排除文本節點

        

         contains():

                   document.documentElement.contains(d);

                  

                   compareDocumentPosition:

                            1: 無關

                            2:居前

                            4:居後

                            8:包含

                            16:被包含

                            document.documentElement.compareDocumentPosition(document.body);//20 = 16+4

                           

                            //兼容性的 contains

                            function contains(refNode, otherNode) {

                                     if (typeof refNode.contains == 'function' && (!client.engin.webkit || client.engin.webkit >= 522)){

                                               return refNode.contains(otherNode);

                                     } else if (typeof refNode.compareDocumentPosition == 'function') {

                                               return !!(refNode.compareDocumentPosition(otherNode));

                                     } else {

                                               var node = otherNode.parentNode;

                                               do {

                                                        if (refNode == node) {

                                                                 return true;

                                                        } else {

                                                                 node = node.parentNode;

                                                        }

                                               } while (node != null);

                                     }

                            }

         插入文本:

                   //這種方式能夠過濾掉 全部的 html 標籤,只剩下文本

                   var div = document.getElementById('div1');

        div.innerText = div.innerText;

                   //firefox 不支持 innerText, 可是可使用 textContent

                  

                   function getInnerText(ele) {

            return typeof ele.textContent == 'string' ? ele.textContent : ele.innerText;

        }

        function setInnerText(ele, txt) {

            if (typeof ele.textContent == 'string') {

                ele.textContent = txt;

            } else {

                ele.innerText = txt;

            }

        }

                  

                   outerText:

                            div.outerText='test';//文本替換div元素

         滾動:

                   //如下方法不經常使用,支持度很差

                   div.scrollIntoViewIfNeeded(true);//當前元素在視口不可見時滾動,設置爲true,元素儘可能顯示在視口中部

                   div.scrollByLines(2);

                   div.scrollByPage(1)

                  

*******************  Chapter 12 DOM2和DOM3 *****************               

DOM變化:

 

         document.implementation.hasFeature('COe','1');//無論怎樣都是返回true

         針對XML命名空間的變化:

                  

         其餘方面的變化:

                   DocumentType類型的變化:

                            document.doctype.publicId;  

                            document.doctype.systemId;

                            document.internalSubset;//幾乎不會用到

                           

                            //相似cloneNode()

                            var newNode = document.importNode(oldNode,true);

                            document.body.appendChild(newNode);

                           

                            //IE 使用 parentWindow

                            document.defaultView||document.parentWindow;

                           

                           

                            document.body.isSupported('HTML','2.0')

                  

                            var div = document.createElement("div");

                            div.setUserData('name', 'test', function (operation, key, value, src, dest) {

                                     //operation: 1.複製  2.導入  3.刪除  4.重命名

                            })

                           

                           

                            var iframe = document.getElementById('myFrame');

                            //IE8以前 contentWindow

                            var doc = ifame.contentDocument || iframe.contentWindow.document;

樣式:

         訪問元素的樣式:

                   DOM樣式屬性和方法:

                            var ele = document.getElementById('div1');

                            var prop, val;

                            for (var i = 0; i < ele.style.length; i++) {

                                     prop = ele.style[i];

                                     val = ele.style.getPropertyCSSValue(prop);

                            }

                  

                   計算的樣式:

                            //null 表示不須要僞元素

                            var comStyle = document.defaultView.getComputedStyle(ele, null);

                            console.log(comStyle.color);//獲取最終實際的值,有效果的值

 

                            //IE

                            var IDComStyle = ele.currentStyle;

                            console.log(comStyle.color);//獲取最終實際的值,有效果的值

                           

         操做樣式表:

                   document.styleSheets

                   var link = document.getElementsByTagName("link")[0];

        var sheet = link.sheet || link.styleSheet;//IE 使用styleSheet

                   //以上的等價表示

                   document.styleSheets;

                  

                   //stylesheets

                   var sheet = document.stylesheets[0];

        var rules = sheet.cssRules || sheet.rules;

        var rule = rules[0];

        rule.style.backgroundColor = 'red';

                  

                   //deleteRule

                   function deleteRule(sheet, index) {

            if (sheet.deleteRule) {

                sheet.deleteRule(index);

            } else if (sheet.removeRule) {//IE

                sheet.removeRule(index);

            }

        }

 

         元素大小:

                   1. 偏移量

                            offsetTop: 元素上邊框與包含元素在內的上內邊框的距離

                            offsetLeft: 元素左邊框與包含元素在內的左內邊框的距離

                            offsetWidth:  元素垂直方向上佔用的空間大小。包括滾動條

                            offsetHeight: 元素水平方向上佔用的空間大小。包括滾動條

                            以上都是隻讀屬性,儘可能避免重複訪問這些屬性,由於每次都會重複計算,影響性能

                           

                            function getEleLeft(ele) {

                                     var left = ele.offsetLeft;

                                     var curEle = ele.offsetParent;

                                     while (curEle != null) {

                                               left += curEle.offsetLeft;

                                               curEle = ele.offsetParent;

                                     }

                                     return left;

                            }

                            function getEleTop(ele) {

                                     var top = ele.offsetTop;

                                     var curEle = ele.offsetParent;

                                     while (curEle != null) {

                                               top += curEle.offsetTop;

                                               curEle = ele.offsetParent;

                                     }

                                     return top;

                            }

                  

                   2. 客戶區大小

                            clientWidth\clientHeight

                           

                            var ele = document.getElementById("");

                            ele.clientWidth;//內容寬度+內邊距

                            ele.clientHeight;//內容高度+內邊距

                            //獲取視口的大小

                            function getViewport() {

                                     if (document.compatMode == 'BackCompat') {

                                               return {

                                                        width: document.body.clientWidth,

                                                        height: document.body.clientHeight

                                               };

                                     } else {

                                               return {

                                                        width: document.documentElement.clientWidth,

                                                        height: document.documentElement.clientHeight

                                               };

                                     }

                            }

                  

                   3. 滾動大小

                            ele.scrollHeight;//沒有滾動條的狀況,元素內容實際的總高度

                            ele.scrollWidth;//沒有滾動條的狀況,元素內容實際的總寬度

 

                            ele.scrollTop;//被隱藏在內容區域上方的高度

                            ele.scrollLeft;//被隱藏在內容區域左側的寬度

                  

                            //使元素滾動到頂部

                            function scrollToTop(ele) {

                                     if (ele.scrollTop != 0) {

                                               ele.scrollTop = 0;

                                     }

                            }

                           

                   4. 肯定元素的大小

                            function getBoundingClientRect(ele) {

                                     var scrollTop = document.documentElement.scrollTop;

                                     var scrollLeft = document.documentElement.scrollLeft;

 

                                     if (typeof arguments.callee.offset != 'number') {

                                               var temp = document.createElement("div");

                                               temp.style.cssTex = "position:absolute;left:0;top:0;";

                                               document.body.appendChild(temp);

                                               arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;

                                               document.body.removeChild(temp);

                                               temp = null;

                                     }

                                     var rect = ele.getBoundingClientRect();

                                     var offset = arguments.callee.offset;

                                     return {

                                               left: rect.left + offset,

                                               right: rect.right + offset,

                                               top: rect.top + offset,

                                               bottom: rect.bottom + offset

                                     };

                                     //console.log(arguments.callee.offset);

                            }

                           

遍歷:

         IE不支持DOM遍歷

         NodeIterator:

                   //獲取全部的元素

                   var itor = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false);

        var node = itor.nextNode();

        while (node) {

            console.log(node.tagName);

            node = itor.nextNode();

        }       

                           

                   //獲取div下面的 p 元素, 自定義過濾器

        var div = document.getElementById("div");

        var filter = function (node) {

            return node.tagName.toLowerCase() == 'p' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;

        };

        var iter = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter, false);     

         TreeWalker:

                   更自由,更靈活的方式;

                  

                   var div = document.getElementById("div");

        var filter = function (node) {

            return node.tagname.tolowercase() == 'p' ? nodefilter.filter_accept : nodefilter.filter_skip;

        };

        var walker = document.createTreeWalker(div, filter, NodeFilter.SHOW_ELEMENT, false);

        walker.firstChild();

        walker.nextSibling();

        var node = walker.firstChild();

        while (node) {

            console.log(node.tagName);

            node = walker.nextSibling();

        }       

範圍:

         DOM中的範圍:

                   Range實例

                            var range1 = document.createRange(),

                                     range2 = document.createRange();

                            var p = document.getElementById('testP');

                            range1.selectNode(p);//包括 p 元素

                            range2.selectNodeContents(p);//只是包括 p 元素的子節點    

                   基本操做

                            var startNode = p.firstChild.firstChild;

                            var endNode = p.lastChild;

                            range1.setStart(startNode, 2);

                            range1.setEnd(endNode, 3);

 

                            var fragment = range1.extractContents();

                            p.parentNode.appendChild(fragment);

 

                            fragment = range1.cloneContents();

                            range1.deleteContents();

 

                            var span = document.createElement("span");

                            range1.insertNode(span);

 

                            range1.surroundContents(span);//將先執行 extractContents(), 將獲取的片斷插入 span 中

                           

                            range1.collapse(true);//true 表示摺疊到起點  false 摺疊到終點

                            range1.collapsed;//查詢是否摺疊

 

                            range1.compareBoundaryPoints(Range.START_TO_START, range2);//-1:沒有任何關係 0:相等  1:包含關係

 

                            //複製範圍

                            var newRange = range1.cloneRange();

                            //清理範圍

                            range1.detach();

                            range1 = null;

         IE8及更早版本中的範圍

                   var ieRange = document.body.createTextRange();

        var canFound = ieRange.findText("hello");//true/false

        console.log(ieRange.text);

 

 

        var canFound = ieRange.findText("hello", 1);//true/false  1:向前搜索  -1: 向後搜索

 

        ieRange.moveToElementText(p);

        ieRange.htmlText;

                           

                   ieRange.moveStart('word', 2);

        ieRange.moveEnd('character', 2);

 

        ieRange.expand('hello');

        ieRange.pasteHTML('<p>test</p>');

        ieRange.collapse(true);

        var isCollapsed = (ieRange.boundingWidth == 0);//是否摺疊

        ieRange.compareEndpoints("StartToStart", range2);

        ieRange.isEqual(range2);

        ieRange.inRange(range2);

        var newRange = ieRange.duplicate();//複製 

                  

*********************    Chapter 13 事件     *********************

事件流:

         事件冒泡:IE

                   IE九、Firefox、Chrome、Safari 事件一直冒泡到 window 對象

         事件捕獲:

                   由於老版本瀏覽器不支持,因此不多使用事件捕獲,建議都使用事件冒泡

         DOM事件流:

                   捕獲階段-->處於目標階段-->冒泡階段

事件處理程序:

         HTML事件處理程序:

                       <!--<input type="button" name="name" value="btn" onclick="alert(this.value)" />-->

                            <!--動態擴展性-->

                            <input type="button" name="name" value="btn" onclick="alert(value)" />

                            <!--表單的擴展性-->

                            <form action="/" method="post">

                                     <input type="text" name="userName" value="admin" />

                                     <input type="button" name="name" value="btnGo" onclick="alert(userName.value)" />

                            </form>

 

 

                            <!--普通方式-->

                            <!--<input type="button" name="name" value="btn" onclick="show(this)" />-->

                            <!--這種是保險的方式,防止方法還沒加載處理,就執行了點擊事件,也是缺點之一 -->

                            <input type="button" name="name" value="btn" onclick="try {show(this);} catch (e) { }" />

        

         DOM0級事件處理程序:

                   var btn = document.getElementById('btn');

        btn.onclick = function () {

            console.log(this.id);//this 指向的是當前的元素

        }

                  

         DOM2級事件處理程序:

                   //addEventListener能夠同時綁定多個事件

        var btn = document.getElementById('btn');

        btn.addEventListener('click', function () {

            console.log(this, id);

        }, false);//true:表示捕獲節點觸發  false:表示冒泡階段觸發

 

        btn.addEventListener('click', function () {

            console.log(this.name);

        }, false);//true:表示捕獲節點觸發  false:表示冒泡階段觸發

 

        //removeEventListenerc 操做的時候只能使用命名的方式

        var handler = function () {

            console.log(this.id);

        }

        btn.addEventListener('click', handler, false);

        btn.removeEventListenerc('click', handler,false);

                  

         IE事件處理程序:

                   var handler = function () {

            console.log(this == window);//attachEvent 時候,this 是全局做用域 window

        };

        btn.attachEvent('onclick', handler);//attachEvent 若是同時綁定多個方法,就會倒序執行

        btn.detachEvent('onclick');

                  

         跨瀏覽器的事件處理程序:

                   var EventUtil = {

            addHandler: function (ele, type, handler) {

                if (ele.addEventListener) {

                    ele.addEventListener(type, handler, false);

                } else if (ele.attachEvent) {

                    ele.attachEvent('on' + type, handler);

                } else {

                    ele['on' + type] = handler;

                }

            },

            removeHandler: function (ele, type, handler) {

                if (ele.removeEventListener) {

                    ele.removeEventListener(type, handler, false);

                } else if (ele.detachEvent) {

                    ele.detachEvent('on' + type, handler);

                } else {

                    ele['on' + type] = null;//DOM0 級方式

                }

            }

        }

                  

事件對象:

         DOM中的事件對象:

                  

                   var btn = document.getElementById('btn');

        btn.onclick = function () {

            //event.preventDefault();//阻止默認事件,這個只有在 cancellable =true 的時候有用

            //event.stopPropagation();//阻止事件冒泡

            alert(event.eventPhase);//click  2 處於目標階段

            //alert(event.type);//click

            //console.log(this.id);//this 指向的是當前的元素

        }

        document.body.addEventListener('click', function () {

            alert(event.eventPhase);//1

        }, true);//捕獲階段

        document.body.onclick = function () {

            alert(event.eventPhase);//3  冒泡階段

        }

         IE中的事件對象:

                   btn.onclick = function () {

            var e = window.event;

            e.cancelable = true;//IE 取消冒泡事件

            e.returnValue = false;//IE取消默認行爲

        }

         跨瀏覽器的事件對象:

                   var EventUtil = {

                           getClipboardText: function (event) {

                var clipData = (event.clipboarData || window.clipboardData);

                return clipData.getData('text');

            },

            setClipboardText: function (event,value) {

                if (event.clipboarData) {

                    return event.clipboarData.setData("text/plain", value);

                } else if (window.clipboardData) {

                    return window.clipboardData.setData("text", value);

                }

            },

                            getWheelDelta: function (event) {

                if (event.wheelDelta) {

                    return client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta;

                } else {

                    return -event.detail * 40;//Firefox

                }

            },

            getButton: function () {

                if (document.implementation.hasFeature('MouseEvents', '2.0')) {

                    return event.button;

                } else {

                    //IE

                    switch (event.button) {

                        case 0:

                        case 1:

                        case 3:

                        case 5:

                        case 7:

                            return 0;

                        case 2:

                        case 6:

                            return 2;

                        case 4:

                            return 1;

                    }

                }

            },

            //對於鼠標事件的 mouseout和mouseover

            getRelatedTarget: function (event) {

                if (event.getRelatedTarget) {

                    return RelatedTarget;

                } else if (event.toElement) {

                    return event.toElement;//IE mouseout

                } else if (event.fromElement) {

                    return event.fromElement;//IE mouseover

                } else {

                    return null;

                }

            },

            getEvent: function (event) {

                return event ? event : window.event;

            },

 

            getTarget: function (event) {

                return event.target || event.srcElement;

            },

            preventDefault: function (event) {

                if (event.preventDefault) {

                    event.preventDefault();

                } else {

                    event.returnValue = false;

                }

            },

            stopPropagation: function (event) {

                if (event.stopPropagation) {

                    event.stopPropagation();

                } else {

                    event.cancelBubble = true;

                }

            },

            addHandler: function (ele, type, handler) {

                if (ele.addEventListener) {

                    ele.addEventListener(type, handler, false);

                } else if (ele.attachEvent) {

                    ele.attachEvent('on' + type, handler);

                } else {

                    ele['on' + type] = handler;

                }

            },

            removeHandler: function (ele, type, handler) {

                if (ele.removeEventListener) {

                    ele.removeEventListener(type, handler, false);

                } else if (ele.detachEvent) {

                    ele.detachEvent('on' + type, handler);

                } else {

                    ele['on' + type] = null;//DOM0 級方式

                }

            }

        }

                  

事件類型:

         UI事件:

                   load\unload\abort\error\select\resize\scroll\

                   img 也可使用 load 事件

         焦點事件:

                   blur(不支持冒泡)\DOMFocusIn\DOMFocusOut\focus(不支持冒泡)\focusin(支持冒泡)\focusout

         鼠標與滾輪事件:

                   click\dbclick\mousedown\mouseenter(不冒泡)\mouseleave(不冒泡)\mousemove\mosueout\mouseover\mouseup                  

                   mousewheel

                   clientX\clientY:相對視口的位置

                   pageX\pageY:相對頁面的位置

                   screenX\screenY:相對屏幕的位置

                   event.shiftKey\event.ctrlKey\event.altKey\event.metaKey(IE8不支持)

                  

                   鼠標按鈕:

                            event.button: 0:左鍵 1:中間滾輪 2:右鍵

                  

                   mousewheel:

                            event.wheelDelta:120倍數表示向前滾動,-120倍數表示向後滾動,Opera 是相反的

                            Firefox使用的DOMMouseScroll事件:-3表示向前滾動,3表示想後滾動

                   觸摸設備:

                            不支持dbclick

                   無障礙性問題:

                            屏幕閱讀器沒法觸發mousedown事件;

                            不要使用mouseover;

                            不要使用dbclick

 

         鍵盤與文本事件:        

                   keydown(任意鍵)\keypress(字符鍵)\keyup\

                   event.keyCode

                   keypress事件:event.charCode

                   DOM3級變化:不推薦

                            不在包含charCode,而是使用key\char

                            location|keyLocation

                            getModifierState('Shift')

                   textInput事件:IE9+

                            對於可編輯區域輸入實際字符纔會觸發,

                            event.data 返回實際字符;

                            event.inputMethod 返回輸入模式

                  

         複合事件:IE9+惟一支持,不推薦

                   compositionstart\compositionupdate\compositionend

                  

         變更事件:

                   刪除節點:

                            DOMNodeRemoved\DOMSubtreeModified\DOMNodeRemoved\DOMNodeRemovedFromDocument

                   插入節點:

                            DOMNodeinserted\DOMSubtreeModified\DOMNodeInsertedDocument

                  

         HTML5事件:

                   contextmenu 右鍵菜單事件

 

                            var div = document.getElementById("div");

                            //右鍵菜單點擊事件

                            div.addEventListener('contextmenu',function(event){

                                     event = event||window.event;

                                     //取消右鍵菜單默認事件

                                     event.preventDefault();

 

                                     var menu = document.getElementById("menu");

                                     menu.style.left=event.clientX+'px';

                                     menu.style.top=event.clientY+'px';

                                     menu.style.visibility='visible';

                            },false);

 

                            var menu = document.getElementById("menu");

                            // menu.onclick=function(){

                            //     event.stopPropagation();

                            // }

                            menu.addEventListener('click',function(){

                                     event.stopPropagation();

                            },false)

 

                            document.onclick=function(){

                                     var menu = document.getElementById("menu");

                                     menu.style.visibility='hidden';

                            }

 

                   beforeunload事件

                            //離開頁面以前的提示

                            window.addEventListener('beforeunload',function(){

                                     var msg ="are you sure to go ...";

                                     event.returnValue=msg;

                                     return msg;

                            },false);

                                              

                   DOMContentLoaded 事件

                            DOM樹造成以後當即調用,而且會在load以前

                            document.addEventListener('DOMContentLoaded',function(){

                                     alert('ok');

                            },false);

                           

                            //對於不支持DOMContentLoaded 的可使用以下方式替代

                            setTimeout(function(){},0);

                   readystatechange 事件

 

                            document.addEventListener('readystatechange',function(event){

                                     if(document.readyState=='interactive' || document.readyState=='complete'){

                                               alert('loaded...');

                                     }

                            },false);

                            //動態添加 script 元素

                            var script = document.createElement('script');

                 script.addEventListener('readystatechange', function (event) {

 

                     if (script.readyState == 'loaded' || event.script == 'complete') {

                         script.removeEventListener('readystatechange', arguments.callee, false);

                     }

                 }, false)

                 script.src = 'test.js';

                 document.body.appendChild(script);

                  

                   pageshow和pagehide事件:

                            bfcache 用來緩存頁面,當時用了瀏覽器 ‘前進’、‘後退’的時候

                            不管頁面是否來自緩存,都會執行pageshow 事件,都是在load事件以後執行

                            event.persisted 表示是否來自bfcache緩存

                            pagehide 在頁面卸載以前觸發

                            指定了onunload事件的頁面會被自動排除在 bfcache 以外

                            //注意這兩個事件都是綁定到 window 對象上,實際目標是document

                             window.addEventListener('pageshow', function () {

                                console.log(event.persisted);

                             }, false);

                   hashchange事件:

                            //url 改變的時候觸發

                 window.addEventListener('hashchange', function (event) {

                     console.log(event.oldURL);

                     console.log(event.newURL);

                     console.log(location.hash);//考慮兼容性,推薦使用

                 }, false);

         設備事件:

                   orientationchange 事件:

                            window.addEventListener('orientationchange', function (event) {

                     console.log(window.orientation);

                 }, false);

 

         觸摸與手勢事件:

                   觸摸事件:

                            touchstart

                            touchmove

                            touchend

                            touchcancel

                   手勢事件:    

                            gesturestart

                            gesturechange

                            gestureend      

                            event.rotate\event.scale

內存和性能:

         事件委託:

                   經過事件冒泡,只爲上層元素添加事件,經過判斷元素目標執行事件

                   也能夠直接爲 document 對象添加事件處理程序

 

         移除事件處理程序:

                   var btn = document.getElementById('btn');

        btn.onclick = function () {

            //移除處理事件

            btn.onclick = null;

            //...替換btn操做

        }

模擬事件:

         DOM中的事件模擬:

                   模擬鼠標事件:

                            var btn = document.getElementById('btn');

                 var event = document.createEvent("MouseEvents");

                 event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

                 //觸發事件

                 btn.dispatchEvent(event);

         IE中的事件模擬:

                   var btn = document.getElementById('btn');

        var event = document.createEventObject();

        event.screenX = 100;

        event.screenY = 0;

        event.clientX = 0;

        event.clientY = 0;

        event.ctrlkey = false;

        event.altKey = false;

        event.shiftKey = false;

        event.button = 0;

        btn.fireEvent('onclick', event);

 

                  

                  

 

*********************    Chapter 14 表單腳本     *********************               

表單的基礎知識:

         document.forms[0];

         document.forms['form2'];

         提交表單:

                   var form1 = document.getElementById("form1");

        form1.submit();//這種方式不會觸發 submit 事件

 

        document.forms[0].addEventListener("submit", function (event) {

            alert('1');

            //組織表單提交的默認事件

            event.preventDefault();

 

        }, false);

    重置表單:

             reset

    表單字段:

             form.elements[0]

             form.elements['txtName']

 

             //修改元素類型

        form1.elements["t"].type = 'checkbox';

 

        focus()\blur():

                 <input type="text" name="t" value="1" autofocus />

文本框腳本:

         選擇文本:

        select():

                 //選中輸入框文本

                 form1.elements["t"].select();

        selectionStart\selectionEnd:

                 //獲取文本選中位置     

                 alert(form1.elements["t"].selectionStart +","+ form1.elements["t"].selectionEnd);

                 //IE的方式

                 document.selection.createRange().text

        setSelectionRange():

                 //設置選擇區域

                 form1.elements["t"].setSelectionRange(1, 2);

                 //通用方式

                 function setSelection(txt, start, end) {

                     if (txt.setSelectionRange) {

                         txt.setSelectionRange(start, end);

                     } else if (txt.createTextRange) {//IE8及如下

                         var range = txt.createTextRange();

                         range.collapse(true);

                         range.moveStart("character", start);

                         range.moveEnd("character", end - start);

                         range.select();

                     }

                     txt.focus();

                 }

        

         過濾輸入:

                   var txt = document.getElementById('txt');

        txt.onkeypress = function (event) {

            //除了 Ctrl 鍵和 其餘字符輸入鍵,都屏蔽掉

            if (!/\d/.test(String.fromCharCode(event.charCode)) && event.charCode > 9 && !event.ctrlKey) {

                event.preventDefault();

            }

        }

             操做剪貼板:

                      cop\cut\paste

                      //獲取剪貼板內容

                      var EventUtil = {

                     getClipboardText: function (event) {

                         var clipData = (event.clipboarData || window.clipboardData);

                         return clipData.getData('text');

                     },

                     setClipboardText: function (event,value) {

                         if (event.clipboarData) {

                             return event.clipboarData.setData("text/plain", value);

                         } else if (window.clipboardData) {

                             return window.clipboardData.setData("text", value);

                         }

                     }

                 }

        

         自動切換焦點:

                   (function () {

            function tab(event) {

                var target = window.event.srcElement;

                if (target.value.length == target.maxLength) {

                    var form = target.form;

                    for (var i = 0,len = form.elements.length; i < len ; i++) {

                        if (form.elements[i] == target) {

                            if (form.elements[i+1]) {

                                form.elements[i+1].focus();

                            }

                            return;

                        }

                    }

                }

            }

            var a = document.getElementById("a");

            var b = document.getElementById("b");

            var c = document.getElementById("c");

            a.addEventListener("keyup", tab, false);

            b.addEventListener("keyup", tab, false);

            c.addEventListener("keyup", tab, false);

        })();               

   

    HTML5約束驗證API:

 

             表單和按鈕均可以設置是否進行默認API的驗證

              <form action="/" method="post" novalidate>

                 <input type="submit" name="btn" value="go" formnovalidate/>

              </form>

選擇框腳本:

                   //添加項

                   var newOpt = new Option('text', 'value');

        sel.add(newOpt,undefined);//推薦

        sel.appendChild(newOpt);//IE8及以前bug

 

                   //直接移動一項到另外一個selection

        var sel = document.getElementById("sel");

        var sel2 = document.getElementById("sel2");

        sel2.appendChild(sel.options[0]);

 

        //向後移動一項

        var opt = sel.options[1];

        sel.insertBefore(opt, sel.options[opt.index + 2]);

表單序列化:

                   function serialize(form) {

            var parts = [],

                field = null,

                optLen,

                opt,

                optVal;

 

            for (var i = 0, len = form.elements.length; i < len; i++) {

                field = form.elements[i];

                switch (field.type) {

                    case "select-one":

                    case "select-multiple":

                        if (field.name.length) {

                            for (var j = 0, optLen = field.options.length; j < optLen; j++) {

                                opt = field.options[j];

                                if (opt.selected) {

                                    optVal = "";

                                    if (opt.hasAttribute) {

                                        optVal = (opt.hasAttribute("values") ? opt.value : opt.text);

                                    } else {

                                        optVal = (opt.attributes["value"].specified ? opt.value : opt.text);

                                    }

                                    parts.push(encodeURIComponent(field.name) + "="+

                                        encodeURIComponent(optVal));

                                }

                            }

                        }

                        break;

                    case undefined:

                    case "file":

                    case 'submit':

                    case 'reset':

                    case 'button':

                        break;

                    case 'radio':

                    case 'checkbox':

                        if (!field.checked) {

                            break;

                        }

                    default:

                        if (field.name.length) {

                            parts.push(encodeURIComponent(field.name) + "=" +

                                        encodeURIComponent(field.value));

                        }

                }

            }

            return parts.join("&");

        }

 

富文本編輯:

         designMode:

                   window.onload = function () {

            window.frames['ifm'].document.designMode = 'on';

        }

         使用 contentEditable 屬性:

 

        var div = document.getElementById("div");

        div.contentEditable = 'true';   

    操做富文本:

             window.onload = function () {

            window.frames['ifm'].document.designMode = 'on';

            //指定富文本指定命令

            window.frames['ifm'].document.execCommand("bold",false,null)

                            //查詢是否可用指定的命令

                            var res = window.frames['ifm'].document.queryCommandEnabled("bold")

                            //查詢富文本是否應用了該命令

                            var res = window.frames['ifm'].document.queryCommandState("bold")

        }

     富文本選區:

            //獲取選區

        var selection = window.frames['ifm'].getSelection();

        //選區文本

        var txt = selection.toString();

        //選區範圍

        var range = selection.getRangeAt(0);

        var span = document.createElement("span");

        span.style.backgroundColor = 'yellow';

        range.surroundContents(span);

 

        //修改選區的樣式

        var range = frames['ifm'].document.selection.createRange();

        range.pasteHTML("<span style='color:red;'>" + range.htmlText + "</span>");

    表單與富文本:

        var form = document.getElementById('form1');

        form.addEventListener("submit", function (event) {

            var target = event.srcElement;

            //提交的時候經過 隱藏域來獲取到 富文本的值後,能夠提交

            target.elements['bak'].value = frames['ifm'].document.body.innerHTML;

        }, false);

 

        

*********************    Chapter 15 使用Canvas 繪圖      *********************                       

基本用法:

         <canvas id="canvas" width="200" height="200">該瀏覽器不支持Canvas</canvas>

         <hr />

    <button onclick="save()">Save</button>

        

                   var canvas = document.getElementById("canvas");

        if (canvas.getContext) {

            var context = canvas.getContext("2d");

            context.fillStyle = '#FF0000';

            context.fillRect(0, 0, 150, 75);

        }

                   //toDataURL

                   function save() {

            var img = canvas.toDataURL('image/png');

            var image = document.createElement("img");

            image.src = img;

            document.body.appendChild(image);

        }

2D上下文:

 

 

 

*********************    Chapter 16 HTML5 腳本編程         *********************                         

跨文檔消息傳遞:XDM

         //主頁面負責發送消息

    var ifm = document.getElementById("ifm").contentWindow;

    ifm.postMessage("msg from here", "http://www.123.com");//來源當前地址文檔

 

    //子頁面 iframe 處理消息

    window.onmessage = function (event) {

        //確認來自的域

        if (event.origin == "http://www.123.com") {

            //處理數據

            proceeMsg(event.data);

            //回發數據  event.source 獲取到的是window 的代理對象

            event.source.postMessage("Received", "http://test.123.com");

        }

    }

 

原生拖放:

         拖放事件:

                   dragstart

                   drag

                   dragend

                   dragenter

                   dragover

                   dragleave\drop

 

                   var div = document.getElementById("target");

        //目標元素,取消瀏覽器的默認行爲,防止自動打開頁面搜索url

        div.addEventListener("dragover", function (event) {

            event = event || window.event;

            event.preventDefault();

        }, false);

        div.addEventListener("drop", function (event) {

            event = event || window.event;

            //獲取 設置的 url ,兼容性(Firefox)

            //var url = event.dataTransfer.getData("url") || event.dataTransfer.getData('text/uri-list');

            //使用 大寫Text 來獲取,兼容性(Firefox)

            var id = event.dataTransfer.getData('Text');

            var target = event.srcElement;

            target.appendChild(document.getElementById(id));

            event.preventDefault();

        }, false);

        //dataTransfer 的使用

        var p = document.getElementById("p");

        p.addEventListener("dragstart", function (event) {

            event = event || window.event;

            event.dataTransfer.setData('text', 'p');//IE中只能設置 'text' 或者 'url'

 

        }, false);

                  

                   effectAllowed/dropEffect:

                            event.dataTransfer.effectAllowed = 'move';

                 event.dataTransfer.dropEffect = 'move';

                                              

                   draggable 可拖動屬性:

                       <p id="p" draggable="true">to drag div</p>

 

媒體元素:

 

歷史狀態管理:

         history.pushState({name:"test"},'','test_04.html')

                  

 

*********************    Chapter 17 錯誤處理與調試         *********************      

                   try{

                           

                   }catch(e){

                            alert(e.message);

                   }       

                   //結果: 返回2

                   function test() {

            try {

                return 0;

            } catch (e) {

                return 1;

            } finally {

                return 2;

            }

        }                

    錯誤類型:

            Error

            EvalError

            RangeError

            ReferenceError

            SyntaxError

            TypeError

            URIError

 

    throw:

            function test1() {

            try {

                //throw 1;

                throw "test error...";

            } catch (e) {

                console.log(e);//1  test error...

            }

        }

    錯誤事件error:

        window.onerror = function (message,url,line) {

            alert(message);

        }

        var a = 1 / 0 + c;//沒有捕捉的錯誤都會觸發 onerror 事件

 

        //圖片也可使用 error 事件

        var img = new Image();

        img.onerror = function (event) {

        }

        img.src = 'fd.jpg';//

 

    常見錯誤類型:

        function foo(str1, str2) {

            //不要使用 if(str2), 由於 傳入0 結果也是 false

            if (typeof str2 =="String" ) {

            }

        }

        基本類型使用 typeof 檢測, 對象則使用 instanceof 檢測

 

    記錄日誌到服務端:(高大上)

        function logError(sev, msg) {

            var img = new Image();

            //使用Image 的方式提交錯誤優點:

            //1. 避免跨域的問題

            //2. 兼容性,全部瀏覽器都支持 Image

            //3. 相對於Ajax,出問題的機率更低

            img.src = "log.ashx?sev=" + sev + "&msg=" + msg;

        }

 

常見的IE錯誤:

 

        document.onclick = function (event) {

            event = event || window.event;

            setTimeout(function () {

                event.returnValue = false;//IE8 會出現找不到成員

            }, 1000);

        }

 

        IE對JavaScript 請求資源的 URL 最長不能超過2083個字符限制,URL路徑限制2048

 

 

*********************    Chapter 18 JavaScript 與 XML       *********************      

 

ECMAScript for XML

瀏覽器對XML DOM 的支持

                   //通常不須要指定 命名空間 和 文檔類型

        var xmlDom = document.implementation.createDocument('', 'root', null);

        var child = xmlDom.createElement("child");

        xmlDom.documentElement.appendChild(child);

 

    DOMParser:  

        //解析xml

        var parser = new DOMParser();

        try {

            var xml = parser.parseFromString("<root><child/></root>", 'text/xml');

            var errors = xml.getElementsByTagName("parsererror");//獲取是否有錯誤節點,錯誤節點名稱 parsererror

            if (errors.length > 0) {

                throw new Error("parsing error!");

            }

 

            console.log(xml.documentElement.tagName);//root

            console.log(xml.documentElement.firstChild.tagName);//child

            var child = xml.createElement("child");

            xml.documentElement.appendChild(child);

 

            var children = xml.getElementsByTagName("child");

            console.log(children.length);//2

        } catch (e) {

 

        }

 

 

    XMLSerializer:

        var serializer = new XMLSerializer();

        var xml = serializer.serializeToString(xmlDom);

        console.log(xml);

    IE8及以前版本中的XML:

             function createDom() {

            if (typeof arguments.callee.activeXString != "string") {

                var versions = ["MSXML2.DOMDocument.6.0",

                "MSXML2.DOMDocument.3.0",

                "MSXML2.DOMDocument"];

                for (var i = 0, len = versions.length; i < len; i++) {

                    try{

                        new ActiveXObject(versions[i]);

                        arguments.callee.activeXString = versions[i];

                        break;

                    }catch(e){

                        //繼續執行

                    }

                }

            }

            return new ActiveXObject(arguments.callee.activeXString);

        }

 

        var xmlDom = createDom();

        xmlDom.loadXML("<root><child/></root>");

        if (xmlDom.parseError != 0) {

            console.log(xmlDom.parseError.errorCode);

            console.log(xmlDom.parseError.line);

            console.log(xmlDom.parseError.linepos);

            console.log(xmlDom.parseError.reason);

        }

        console.log(xmlDom.documentElement.tagName);

        //添加子節點

        xmlDom.documentElement.appendChild(xmlDom.createElement("child"));

 

        序列化獲取xml字符串

                 var xml = xmlDom.xml;

 

        加載xml文件

                 var xmlDom = createDom();

                 xmlDom.async = false;//同步

                 xmlDom.load("example.xml");

                 //.....

 

             異步加載和事件綁定

                 var xmlDom = createDom();

                 xmlDom.async = true;//異步

                 xmlDom.onreadystatechange = function () {

                     if (xmlDom.readyState == 4) {

                         //.......

                     }

                 }

                 //必須在事件綁定以後 load

                 xmlDom.load("example.xml");

        

         跨瀏覽器處理XML:

                   function parseXML(xml) {

            var xmlDom = null;

            if (typeof DOMParser != 'undefined') {

                xmlDom = new DOMParser();

                xmlDom.parseFromString(xml, 'text/xml');

                var errors = xmlDom.getElementsBytagName("parseerror");

                if (errors.length > 0) {

                    throw new Error("parsing error:"+errors[0].textContent);

                }

            } else if (typeof ActiveXObject != 'undefined') {

                xmlDom = createDom();

                xmlDom.loadXML(xml);

                if (xmlDom.parseError != 0) {

                    throw new Error("parsing error:" + xmlDom.parseError.reason);

                }

            } else {

                throw new Error("No Xml parser available");

            }

            return xmlDom;

        }

        //解析xmlDom

        function serializerXml(xmlDom) {

            if (typeof XMLSerializer != 'undefined') {

                return (new XMLSerializer()).serializeToString(xmlDom);

            } else if (typeof xmlDom.xml != "undefind") {

                return xmlDom.xml;

            } else {

                throw new Error("could'n serialize xmlDom");

            }

        }

 

 

*********************    Chapter 19 E4X        *********************      

 

 

 

 

*********************    Chapter 20 JSON      *********************      

JavaScript Object Notation

 

對象的屬性名稱必須使用雙引號

{"name":"kk"}

 

全局對象JSON:

         stringfy():

                   值爲undefined 的值會被忽略

 

                   var book = { "title": "Time", "edtion": '2010', 'price': 20 };

        //正常的序列化

        console.log(JSON.stringify(book));

        //使用縮進的方式

        //{

        //    --"title": "Time",

        //    --"edtion": "2010",

        //    --"price": 20

        //}

        console.log(JSON.stringify(book,null,'--'));

        //過濾字段的方式

        console.log(JSON.stringify(book, ['title']));// {"title":"Time"} 返回數組中的字段

        //使用方法進行過濾

        console.log(JSON.stringify(book, function (key, val) {

            switch (key) {

                case 'price':

                    return "$" + val + ".00";

                case "title":

                    return undefined;//去掉title

                default:

                    return val;

            }

        }));//{"edtion":"2010","price":"$20.00"}

    toJSON:

        var book = {

            "title": "Time",

            "edtion": '2010',

            'price': 20,

            toJSON: function () {

                return this.title;

            }

        };

        //1. 若是存在 toJSON ,則直接調用 toJSON

        //2. 若是存在第二個參數,則應用函數過濾器,傳入的值是第一步返回的值

        //3. 對第二步的值進行序列化

        //4. 若是提供了第三個參數,執行相應的格式化

        console.log(JSON.stringify(book));//"Time"

 

         parse()

                   //使用第二個參數進行還原操做

        JSON.parse(txt, function (key,val) {

            if (key == "time") {

                return new Date(val);

            }

            else {

                return val;

            }

        })

 

 

*********************    Chapter 21 Ajax 與 Comet    *********************      

 

XMLHttpRequest 對象:

         響應屬性:

                   responseText:

                   responseXML:

                   status:

                   statusText:

 

         同步請求:

                   var xhr = new XMLHttpRequest();

        //同步請求的方式

        xhr.open("get", "test.ashx", false);

        xhr.send(null);

        if ((xhr.status >= 200 && xhr.status < 300)  || xhr.status == 304) {

            console.log(xhr.responseText);

        } else {

            console.log("error: " + xhr.status);

        }

    異步請求:

             readyState:

                       0:未初始化

                       1:啓動

                       2:發送

                       3:接收

                       4:完成

 

             var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function () {

            if (xhr.readyState == 4) {

                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {

                    console.log(xhr.responseText);

                } else {

                    console.log("error: " + xhr.status);

                }

            }

        }

        xhr.open("get", "test.ashx", true);

        xhr.send();  

 

        //能夠設置終止請求

        xhr.abort();

        xhr = null;

    HTTP頭部信息:

             Accept

             Accept-Charset  

             Accept-Encoding

             Accept-Language

             Conenction

             Cookie

             Host

             Referer

             User-Agent

 

    GET

             var url = "Test.ashx";

        addUrlParams(url, "name", "kk");

        //get 請求的參數的查詢字符串須要進行 encodeURIComponent編碼

        xhr.open("get", url, true);

 

        //設置自定義的請求頭,必須在 open()以後,send()以前

        xhr.setRequestHeader("MyHeader", "haha");

 

        xhr.send();

 

    POST

        xhr.open("post", "Test.ashx", true);

        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        var form = document.getElementById("f1");

        xhr.send(serialize(form));

 

XMLHttpRequest 2級:

         FormData:

                   var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function () {

            if (xhr.readyState == 4) {

                if (xhr.status == 200) {

                    //...

                }

            }

        }

        xhr.open('post', 'Tst.ashx', true);

        xhr.send(new FormData(document.getElementById('f1')));

         超時設定:

                   xhr.open('post', 'Tst.ashx', true);

        xhr.timeout = 1000;//超時設置爲 1s

        xhr.ontimeout = function () {

            console.log('request over time');

        }

        xhr.send(new FormData(document.getElementById('f1')));

         overrideMimeType() 方法:

                   xhr.open('post', 'Tst.ashx', true);

        //強制響應對象做爲 XML 處理

        xhr.overrideMimeType("text/xml");

        xhr.send(new FormData(document.getElementById('f1')));

 

進度事件:

         load:

                   //不須要去檢查 readyState=4

                   xhr.onload = function () {

            if ((xhr.status >= 200 && xhr.status < 300)||xhr.status == 304){

                console.log(xhr.responseText);

            } else {

                //

            }

        }

         progress:

                   //接收數據期間週期性的觸發

                    xhr.onprogress = function (event) {

            var divStatus = document.getElementById("status");

            if (event.lengthComputable) {

                divStatus.innerHTML = "Received: " + event.position + ", total:" + event.totalSize + " bytes";

            }

        }

        

跨源資源共享:CORS

         IE對CORS的實現:

                   var xdr = new XDomainRequest();

        xdr.onload = function () {

            console.log(xhr.responseText);

        }

        xdr.onerror = function () {

            console.log("error");

        }

        xdr.timeout = 1000;

        xdr.ontimeout = function () {

            console.log("...");

        }

 

        //get

        xdr.open("get", "http://.......");

        xdr.send(null);

 

        //post

        xdr.open("post", "http://......");

        xdr.contentType = "application/x-www-form-urlencoded";

        xdr.send("name=test&age=18");  

         其餘瀏覽器對CORS的實現:

                   直接使用 XMLHttpRequest 方式,傳入絕對URL

        

                   不能使用 setRequestHeader() 設置自定義頭部

                   不能發送和接收cookie

                   調用getAllResponseHeader()方法總會返回空字符

         Preflighted Requests:

                   IE10及以前不支持

         帶憑據的請求:

                   IE10及以前不支持

                   Access-Control-Allow-Credentials:true

         跨瀏覽器的CORS:

                   function createCROSRequest(method, url) {

            var xhr = new XMLHttpRequest();

            if ("withCredentials" in xhr) {

                xhr.open(method, url, true);

            } else if (typeof XDomainRequest != 'undefined') {

                xhr = new XDomainRequest();

                xhr.open(method, url);

            } else {

                xhr = null;

            }

            return xhr;

        }

 

        var request = createCROSRequest("get", "http://...");

        if (request) {

            request.onload = function () {

                //處理responseText

            };

            request.send();

        }

其餘跨域技術:

         圖像Ping

                   只能應用於get請求

                   不能處理響應數據

                   var img = new Image();

        img.onload = img.onerror = function () {

            console.log('OK');

        }

        img.src = "http://www.xx.com?name=test";

        

         JSONP:

                   JSON with padding

                   安全性問題得不到保證

 

 

        function handler(response) {

            console.log(response.data);

        }

        var script = document.createElement("script");

        script.src = 'http://www.xx.com?callback=handler';

        document.body.insertBefore(script, document.body.firstChild);

   

    Comet:

             短輪詢和長輪詢

             HTTP流

             //IE不兼容

             function createStreamClient(url,process,finish) {

            var received = 0;

            var xhr = new XMLHttpRequest();

            xhr.open('get', url, true);

            xhr.onreadystatechange = function () {

                     //不斷從服務端接收數據,readyState 週期性變爲3

                if (xhr.readyState == 3) {

                    var res = xhr.responseText.substring(received);

                    received += res.length;

                    process(res);

                } else if (xhr.readyState == 4) {

                    finish(xhr.responseText);

                }

            }

            xhr.send();

            return xhr;

        }

        var client = createStreamClient("http://", function (data) { }, function (data) { })

    服務器發送事件:

             SSE: Server-Sent Events   

             IE不兼容

 

             var es = new EventSource("Test.ashx");

        //open mesasge error

        es.onmessage = function (event) {

            var data = event.data;

            console.log(es.readyState);//0:正在鏈接  1:打開了鏈接   2:關閉了鏈接

            console.log(data);

        }

        //es.close();

 

        //服務端

        public void ProcessRequest(HttpContext context)

        {

            //var header = context.Request.Headers["MyHeader"];

            //context.Response.Headers["MyHeader"] = header;

            context.Response.ContentType = "text/event-stream";

            context.Response.Write("data:test" );//須要使用data: 前綴

            context.Response.Write("\n\n");//必需要以 空行結尾

        }

    Web Sockets:

             socket 狀態:

                       WebSocket.OPENING(0)

                       WebSocket.OPEN(1)  

                       WebSocket.CLOSING(2)  

                       WebSocket.CLOSE(3)         

             var socket = new WebSocket("http://www.xx.com");

        socket.onopen = function () {

        }

        socket.onerror = function () {

        }

        socket.onclose = function (event) {

            console.log(event.wasClean);

            console.log(event.code);

            console.log(event.reason);

        }

        socket.send("haha");

 

        socket.close();

 

 

*********************    Chapter 22 高級技巧     *********************      

高級函數:

         安全的類型檢測:

                   function isArray(val) {

            return Object.prototype.toString.call(val) == '[object Array]';

        }

    做用域安全的構造函數:

             function Person(name, age) {

            if (this instanceof Person) {

                //這裏檢測了this , 也就是若是沒有 使用 new 關鍵字,也不會綁定到window 對象上

                this.name = name;

                this.age = age;

            } else {

                return new Person(name, age);

            }

        }

        //沒有使用 new

        var p = Person("test", 20);

        console.log(p.name);  

 

 

             //繼承的實現

        function Person(name, age) {

            if (this instanceof Person) {

                //這裏檢測了this , 也就是若是沒有 使用 new 關鍵字,也不會綁定到window 對象上

                this.name = name;

                this.age = age;

            } else {

                return new Person(name, age);

            }

        }

 

        function Man(name, age) {

            Person.call(this, name, age);

            this.gender = 1;

        }

        //this instanceof Person  == true

        Man.prototype = new Person();//這樣子使用以後 ,this 就能夠是Person

 

        var m = new Man('man', 30);

        console.log(m.name);

    惰性載入函數:

                   function createXHR() {

            if (typeof XMLHttpRequest != 'undefined') {

                createXHR = function () {

                    return new XMLHttpRequest();

                }

            } else if (typeof ActiveXObject != 'undefined') {

                createXHR = function () {

                    var versions = ["MSXML2.XMLHttp6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];

                    for (var i = 0, len = versions.length; i < len; i++) {

                        try {

                            new ActiveXObject(versions[i]);

                            arguments.callee.activeString = versions[i];

                            break;

                        } catch (e) {

                            //next

                        }

                    }

                    return new ActiveXObject(arguments.callee.activeString);

                }

            } else {

                createXHR = function () {

                    throw new Error("No XHR...");

                }

            }

        }

 

         函數綁定:

                   var handler = {

            mesasge: "hello handler",

            handlerClick: function () {

                alert(this.mesasge);

            }

        };

 

        var btn = document.getElementById("btn");

 

        //btn.addEventListener("click", handler.handlerClick);//undefined 

        //自定義bind() 函數綁定方法,指定 this

        btn.addEventListener("click", bind(handler.handlerClick, handler));//hello handler

        //ES5 原生bind() 方法

        //btn.addEventListener("click", handler.handlerClick.bind(handler));//hello handler

 

        function bind(fn,context) {

            return function () {

                fn.apply(context, arguments);

            }

        }

 

         函數柯里化:

                   function curry(fn) {

            var args = Array.prototype.slice.call(arguments, 1);

            return function () {

                console.log(Array.isArray(arguments));//false

                var innerArgs = Array.prototype.slice.call(arguments);// arguments 類型變爲 Array

                console.log(Array.isArray(innerArgs));//true

                var finnalArgs = args.concat(innerArgs);

                return fn.apply(null, finnalArgs);

            };

        }

 

        function add(num1, num2) {

            return num1 + num2;

        }

 

        var curAdd = curry(add,10);

        var res = curAdd(3);

        console.log(res);//13

                  

                   //柯里化與bind的使用

                   function bind(fn, context) {

            var args = Array.prototype.slice.call(arguments, 2);

            return function () {

                var innerArgs = Array.prototype.slice.call(arguments);

                var finArgs = args.concat(innerArgs);

                return fn.apply(context, finArgs);

            };

        }

 

        var handler = {

            mesasge: "hello handler",

            handlerClick: function (name,event) {

                alert(this.mesasge + ", Name: " + name);

            }

        };

 

        var btn = document.getElementById("btn");

        btn.addEventListener("click", bind(handler.handlerClick, handler, 'btn'));// 

        //ES5

        btn.addEventListener("click", handler.handlerClick.bind(handler,"btn");// 

 

防篡改對象:

         不可擴展對象:

                   var person = { 'name': "jk" };

        console.log(Object.isExtensible(person));//true

        //禁止擴展對象

        Object.preventExtensions(person);

        console.log(Object.isExtensible(person));//false

        person.age = 19;

        console.log(person.age);//undefined

         密封的對象:

                   Object.seal(person);

        delete person.name;

        console.log(person.name);//jk

        console.log(Object.isSealed(person));//true

        console.log(Object.isExtensible(person));//false

         凍結的對象:

                   Object.freeze(person);//不可擴展,密封的,writable =false

        Object.isFrozen(person);

                  

高級定時器:

         重複的定時器:

                   var div = document.getElementById("div");

        setTimeout(function () {

            var left = parseInt(div.style.left) + 5;

            console.log(left);

            div.style.left = left + "px";

            if (left < 500) {

                //重複性

                setTimeout(arguments.callee, 25);

            }

        }, 25)

 

         Yielding Processes:

        

                   function trunk(arr,process,context) {

            setTimeout(function () {

                var item = arr.shift();

                process.call(context, item);

                if (arr.length > 0) {

                    setTimeout(arguments.callee, 100);

                }

            }, 100);

        }

        

         函數節流:

                   function throttle(method,context) {

            clearTimeout(method.tId);

            method.tId = setTimeout(function () {

                method.call(context);

            }, 100);

        }

        function resizeDiv() {

            var div = document.getElementById("div");

            div.style.height = div.offsetWidth + "px";

        }

 

        window.onresize = function () {

            throttle(resizeDiv);

        }

         自定義事件:

                   function EventTarget() {

            this.handlers = {};

        }

 

        EventTarget.prototype = {

            constructor: EventTarget,

            addHandler: function (type, handler) {

                if (typeof this.handlers[type] == "undefined") {

                    this.handlers[type] = [];

                }

                this.handlers[type].push(handler);

            },

            fire: function (event) {

                if (!event.target) {

                    event.target = this;

                }

                if (this.handlers[event.type] instanceof Array) {

                    var handlers = this.handlers[event.type];

                    for (var i = 0; i < handlers.length; i++) {

                        handlers[i](event);

                    }

                }

            },

            removeHandler: function (type,handler) {

                if (this.handlers[type] instanceof Array) {

                    var handlers = this.handlers[type];

                    for (var i = 0; i < handlers.length; i++) {

                        if (handlers[i] == handler) {

                            break;

                        }

                    }

                }

                handlers.splice(i, 1);

            }

        }

 

        //Demo

        function handleMsg(event) {

            console.log("Msg:" + event.message);

        }

 

        var target = new EventTarget();

        target.addHandler("message", handleMsg);

        target.fire({type:"message",message:"this is test!"});

        target.removeHandler("message", handleMsg);

        target.fire({ type: "message", message: "this is test!" });

 

拖放:

                   var dargDrop = function () {

            var dragging = null;

 

            function handleEvent(event) {

                var target = event.srcElement;

                switch (event.type) {

                    case "mousedown":

                        if (target.className.indexOf("draggable") > -1) {

                            dragging = target;

                        }

                        break;

                    case "mousemove":

                        if (dragging != null) {

                            dragging.style.left = event.clientX + "px";

                            dragging.style.top = event.clientY + "px";

                        }

                        break;

                    case "mouseup":

                        dragging == null;

                        break;

                }

            }

            return {

                enable: function () {

                    document.addEventListener("mousedown", handleEvent);

                    document.addEventListener("mousemove", handleEvent);

                    document.addEventListener("mouseup", handleEvent);

                },

                disable: function () {

                    document.removeEventListener("mousedown", handleEvent);

                    document.removeEventListener("mousemove", handleEvent);

                    document.removeEventListener("mouseup", handleEvent);

                }

            };

        }();

 

        dargDrop.enable();

 

*********************    Chapter 23 離線應用與客戶端存儲     *********************      

離線檢測:

                   navigator.onLine;//狀態

        window.ononline = function () {

        }

        window.onoffline = function () {

        }

        

應用緩存:

         緩存文件關聯:

                   <html manifest="/offline.manifest">

        

         applicationCache的status:

                   0:無緩存

                   1:閒置

                   2:檢查中

                   3:下載中

                   4:更新完成

                   5:廢棄

                  

                   applicationCache.update();

 

數據存儲:

         Cookie:

                  

         IE用戶數據:

                  

         Web存儲機制:

                   Storage:

                           

                   sessionStorage:

                            瀏覽器關閉後消失

                            for (var i = 0; i < sessionStorage.length; i++) {

                                     var key = sessionStorage.key(i);

                                     var val = sessionStorage.getItem(key);

                            }

 

                            for (var key in sessionStorage) {

                                     var val = sessionStorage.getItem(key);

                            }

 

 

                   localStorage:

                            localStorage.name = 'test';

                            console.log(localStorage.getItem('name'));

                            localStorage.removeItem('name');

 

                   storage事件:

                            event屬性:

                                     domain

                                     key

                                     newValue

                                     oldValue

 

 

*********************    Chapter 24 最佳實踐     *********************      

可維護性:

         什麼是可維護的代碼

        

         代碼約定

        

         鬆散耦合

        

         編程實踐

                   尊重對象的全部權:

                            不要爲實例或原型添加屬性

                            不要爲實例或原型添加方法

                            不要重定義已存在的方法

                   避免全局量

                            命名空間的使用方式:

                                     var MyTool = {}

                                     MyTool.EventUtil={}

                                     MyTool.CookieUtil={}

                   避免與null進行比較:

                           

                   使用常量:

                            重複值

                            用戶界面字符串

                            URLs

                            任意可能會更改的值

性能:

         注意做用域:

                   避免全局查找

                   避免with語句

         選擇正確的方法:

                   避免沒必要要的屬性查找

                            減小算法複雜度

                                     O(1)

                                     O(n)

                   優化循環

                            減值迭代:從最大值開始到0的循環

                            簡化終止條件:

                            簡化循環體:

                            使用後測試循環:do-while

                   展開循環:

                  

                   避免雙重解釋:

                            eval()或者Function構造函數或者setTimeout()傳入字符串

        

                   性能的其餘注意事項:

                            原生方法較快

                            Switch語句較快

                            位運算符較快

        

         最小化語句數:

                   多個變量聲明:

                            var i=0,name="jk",arr=[]

                   插入迭代值:

                                     var val = values[i];

                                     i++;

                            優化:

                                     var val= values[i++];

                   使用數組和對象字面量:

                            var person={};

                            var arr=[1,2,3];

                  

         優化DOM交互:

                   最小化現場更新:

                            var list = document.getElementById("myList"),

            fragement = document.createDocumentFragment(),

            item, i;

 

                            for (i = 0; i < 10; i++) {

                                     item = document.createElement("li");

                                     fragement.appendChild(item);

                                     item.appendChild(document.createTextNode("Item" + i));

                            }

                            list.appendChild(fragement);

                   使用innerHTML

                  

                   使用事件代理

                            使用的是事件冒泡的原理

                  

                   注意HTMLCollection:

                            var imgs = document.getElementsByTagName("img"),img;

                            for (var i = 0, len = imgs.length; i < len; i++) {

                                     img = imgs[i];

                                     //處理

                            }

 

部署:

         構建過程:

                   知識產權問題

                   文件大小

                   代碼組織

                  

                   Ant構建工具

         驗證:

                   JSLint

         壓縮:

                   文件壓縮:

                            刪除額外的空白

                            刪除全部註釋

                            縮短變量名

                   HTTP壓縮:

 

*********************    Chapter 25 新興的API  *********************               

相關文章
相關標籤/搜索