Javascript 高级程序设计--总结【四】

*******************************  Chapter 11 DOM扩展  *******************************

主要的扩展是 选择符API 和 HTML5

选择符API:

         document.querySelector('.img');

         document.querySelector('#test');

         document.querySelectorAll('a');

         //这个方式浏览器支持很少,返回是否可以查询得到的结果

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

元素遍历:

         //这种方式就不会考虑后台元素的 空白文本节点了,

         //因为使用 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 文档模式版本号  5、6、7、8、9、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

                   IE9、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  *********************               

    

猜你喜欢

转载自www.cnblogs.com/yougmi/p/8980128.html