zoukankan      html  css  js  c++  java
  • Javascript J更深层次的理解avascript 基础知识

    eval全局函数

    dojo loader会看到如下的功能
       var eval_ = new Function('return eval(arguments[0]);'); //Function 函数是在顶级作用域下执行, 但执行效率更慢, 但使用这样的方法不会污染全局变量。而且调用的是顶级作用域
        eval('var i =100;');
        alert(i); // 100
        eval_('var b = 100');
        //alert(b); //错误, b 未定义
    
    
    
    
        var where = '我在国外'; //全局作用域的where
        function test() {
            var where = '我在国内'; //闭包的where
            eval_('alert(where)'); //我在国外, 全局作用域
            eval('alert(where)');//我在国内, 局部全用域
            window.eval('alert(where)'); //我在国外 IE6/7/8 我在国内。不会採用全局作用域。 能够使用execScript
        }
        test()

    dojo的kernal模块中也会有一个eval函数, 代码和解释例如以下 

    (Function("d", "d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo);
    	/*=====
    	dojo.eval = function(scriptText){
    
    		//  尝试在全局作用域下运行角本字符串(scriptText), 除了IE不能支持,其他浏览器都能够正确的在全局作用域下运行, IE下运行
    		    dojo.eval('var pi = 3.14');
    		    alert(pi)  //pi undefined;
                要在IE中运行全局变量
                dojo.eval("window.pi = 3.14");
                
    		    IE 下要运行全局变量, 仅仅能使用execScript, 可是它不会返回值。 而且不能终止运行
    	*/
    	

    对像的属性检測与枚举

    Javascript 对于有下面几个方法用于属性的检測

    • in 操作符 , 假设对象的自有属性或者继承属性有包括被检測的属性, 则返回ture, "toString" in { x: 'hello'} //true;
    • hasOwnProperty() 检測给定的名字是否为对像的自有属性,假设是,返回true, 对于继承属性,返回false;
    • propertyIsEnumerable() 是hasOwnProperty的增强版, 检測自有属性。 而且可枚举
    • for/in 枚举对像的属性的可枚举属性包括(自有属性和继承属性),不枚举内置方法("toString" )。 但自已重写的内置方法,可被枚举
    • toString, toLocaleString, valueOf 等内置属性不可枚举, Object.prototype.propertyIsEnumerable('toString') 返回true, 但对于代码定义的toString方法。是可枚举的(大部分自已定义的属性都可枚举), 但在IE6之前。自已又一次定义的内置方法,还是不可枚举. 能够通过下面代码进行调整
     /*
           定义一个扩展函数。用来将第二个以及之后的參数。 拷贝到第一个參数
           但在IE下,有一个bug, 就是对于自已定义的内置方法(如在第二个參数对像里有定义toString方法, 那么IE6下for/in不会枚举到toString方法。也就不会复制这个自己定义方法
           所以在代码的里须要显示的检測它
           多个对像时,參数右则的属性等级更高
         */
            var extend = (function(){
    
                for(var p in {toString:null}){
                    return function(o){
                        for(var i = 1, len = arguments.length; i < len; i++){
                            var source = arguments[i];
                            for(var prop in source) o[prop] = source[prop];
                        }
                        return o;
                    }
                }
                // IE 6
                var protoprops = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'constructor', 'propertyIsEnumerable'];
                return function(o){
                    for(var i = 1, len = arguments.length; i < len; i++){
                        var source = arguments[i];
                        for(var prop in source) o[prop] = source[prop];
                        for(var j = 0; j < protoprops.legnth; j++){
                            prop = protoprops[j];
                            if(source.hasOwnProperty(prop)) o[prop] = source[prop];
                        }
                    }
                    return o;
                }
    
            })()

    isString 等方法的实现

    /*
            著名大师 Douglas Crockford 的实现方法
            但对于 instaceof 有一个局限。 instaceof 在两个页面,如A 页面定义了isString方法, 那么能过<iframe name='bPage'> 框架,载入的 B 页面,并定义 var test = new String('test')
            window.onload = function(){
                isString(window.bPage.test); // false;
            }
         */
        function isString(i){
            return typeof i === 'string' || i instanceof String;  // instanceof 用于检測 new String() 创建的字符串
        }
        /*
            有一个小缺点:假设其他的库又一次定义了继承的String类,那么会返回 [object Object], 而上面的方法能够检測到这个是一字符串
         */
        function isString(i){
            return {}.toString.call(i) === "[object String]";
        }

    toArray 方法的实现, IE8 下有差别

    toArray 方法主要将类数组对像(arguments, NodeList) 变为数组对像, 但在IE8及下面,不能将html元素转变为Javascript对像,所以会报错

     efficient = function(obj, offset, startWith){
            console.log('efficient');
            return (startWith || []).concat(Array.prototype.slice.call(obj, offset||0))
        }
        _toArray = parseInt(window.navigator.appVersion.split('MSIE ')[1]) <= 8 ?

    (function(){ function slow(obj, offset, startWith){ var arr = startWith||[]; for(var x = offset || 0; x < obj.length; x++){ arr.push(obj[x]); } return arr; } return function(obj){ return ((obj.item) ? slow : efficient).apply(this, arguments); //假设仅仅决断是否为IE, has(ie), 那么IE9以上的浏览器也会调用slow方法。效率就慢了 }; })() : efficient window.onload = function(){ var input = document.getElementsByTagName('input') _toArray(input)[0].value = '12'; //IE8及下面的浏览器, 不支持obj对像为非javascript对像 }


    for 循环里的 i++ 与 ++i

    这两种写法的效果是一样的。但i++在使用时。会创建一个地址来保存i原来的。添加内存,而++i是直接添加 i 的值, 全部最好使用 for(var i=0; i < 100; ++i) , 源码来自 dojo/_base/array.js

    异或(^)的使用

    用于every 和 some的推断。 源码来自dojo/_base/array.js
    function everyOrSome(some){
    		var every = !some;
    		return function(a, fn, o){
    			var i = 0, l = a && a.length || 0, result;
    			if(l && typeof a == "string") a = a.split("");
    			if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
    			if(o){
    				for(; i < l; ++i){
    					result = !fn.call(o, a[i], i, a);  //一定要加!运算符。转换为boolean类型
    					if(some ^ result){<span style="white-space:pre">	</span>//some 设置为true, 当遇到一个false时,直接返回true; every 即some取反。 every = false, 当遇到fn计算结果为false, 取反后为 true, 那么 false ^ true 为 true, 那么返回 !true.
    						return !result;
    					}
    				}
    			}else{
    				for(; i < l; ++i){
    					result = !fn(a[i], i, a);
    					if(some ^ result){
    						return !result;
    					}
    				}
    			}
    			return every; // Boolean
    		};
    	}


    数组length的相关问题

    学习dojo/quers.js源码中,须要检測能否够扩展数组。 假设是老的浏览器(IE6, 7), 则不能对数组进行扩展. 假设能够扩展数组。那么能够将NodeList 类的原型设定为[], 否则为{}.


    function A(){}
    A.prototype=new Array();
    var a=new A();
    m.push('a','b','c');
    alert(a);//IE6 7:0 其它:3
    alert(a[2]);//全部浏览器:'c', 当使用原型继承数组时。IE 6 7下length会始终为0,不管你有多少个元素,其它浏览器则正常。


    选择器的兼容性


    getElementById, getElementsByTagName 全部浏览器支持 
    getElementsByClassName IE8及下面不支持
    querySelectorAll, IE7及下面不支持 

    对querySelectorAll的思考

    <div><p id="foo"><span><i><i></span></p></div>
    <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"></script>
    <script>
        var foo = document.getElementById("foo");
        // should return nothing
        alert( dojo.query('div span', foo).length ); //0
        // will return the SPAN (booo!)
        alert( foo.querySelectorAll('body div span').length );  // 1
    </script>

    IE8 及以上浏览器都支持 querySelectorAll方法, 可是在元素上调用时,指定的选择器仍然在整个文档中进行匹配。 然后过滤出结果集,以便结果集只包括指定元素的后代元素, 也就是说你能够指定"body div span" 选择器字符串,字符串能够包括元素的祖先。而不不过 span.

    这样会导致使用时不够直观, 并且跟寻常库的使用方式也不一样

        // jQuery
          $("#foo").find("> span");
         
          // DOM  document.getElementById("foo").querySelectorAll(">span") 不支持 >span 这样的css选择符
          document.getElementById("foo").querySelectorAll(":root > span") //须要配合:root等于 div#foo, 而不是document element
    

    错误的处理

    	
    
        var selector = "div:foo";
          try {
            document.querySelectorAll(selector);
          } catch(e) {
            alert(selector.slice(e.position)); // ":foo"
          }
    

    假设指定选择符有问题, querySelectorAll 会报错, 所以必须经过 try{}catch(e){} 处理

    dojo 中在使用querySelectorAll 时, 会构建一个零时 id, 然后从 foo的上级中查找 foo.querySelectorAll("span i"), 会等于 div.querySelectorAll("[id='foo'] span i");

    getAttribute


    getAttribute 的性能要比 element.id, element.src 等效率上要低,但比getAttributeNode的性能要高。

    对于IE7 等老版的浏览器, 不能获得placeholder, 而attributes['placeholder'] 或者 getAttributeNode('placeholder').nodeValue 能够获得.  


    注意: DOJO 的 dom-attr.js 没有修复这个bug, 而jQuery是正常的能够返回 placeholder的值

    offsetLeft bug 问题

    IE8 中offsetLeft 和 offsetTop 会包括父元素border的宽度, 而其他浏览器则没有。 并且在dojo的解决方式是减去父元素的border值,假设在定位元素中单多了一个div容器(border:0), 那么减去的是0, 而不是最外层容器的border 5px;

    scrollLeft 问题

    在使用scrollLeft 获取滚动栏的位置时,须要考虑 dir="rtl" 时,文档从右向左, 滚动栏向右移动时,IE返回正值(IE8及以上,是相对于浏览器右端的值,而IE7是相对于左端的值),而其他浏览器是负值。 在现实代码中不用考虑这样的情况,但在阿拉伯语的网页中,须要考虑

    document.body

    在dojo/_base/window.js 中有一个 body(document)方法,我们平时能够直接使用document.body来调用,可是在xhtml中,不能使用这样的方法,仅仅能使用document.getElementsByTagName('body')[0]

    parentWindow 与 defaultView

    parentWindow 是IE特有的属性, 通过document.parentWindow 或者 document.defaultView 获得文档所在的Window对像。

    在dojo的dom-geometry的docScroll获取滚动栏位置(可能是窗体滚动栏,也可能是frame的滚动栏),所以须要依据传入的document来获得Window对像.

    innerText  与 innerHTML

    dojo-prop 中设置元素的文本时,会调用textContent, 而不会调用 innerText, 而是创建一个createTextNode('value'), 原因例如以下 http://msdn.microsoft.com/en-us/library/ms533899%28v=VS.85%29.aspx

    1. innerText  仅仅在block element 中有效,假设你在<hr>元素上调用,会报错

    2. 对于 html, table, tBody, tFoot, tHead, and tr, innerText & innerHTML 是仅仅读属性

    还须要注意一个问题, 在清除元素的子节点时。一般会使用 removeChild() 方法, 可是removeChild在IE中会导致内存泄漏。 所以能够使用 innerHTML = "" ;



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    《影响力》 一个活生生的例子(转载)
    《激荡三十年》
    百度编辑器UEditor ASP.NET示例Demo 分类: ASP.NET 2015-01-12 11:18 347人阅读 评论(0) 收藏
    网站通用登录模块代码 分类: ASP.NET 2014-12-06 10:49 614人阅读 评论(0) 收藏
    网站通用登录模块代码 分类: ASP.NET 2014-12-06 10:49 615人阅读 评论(0) 收藏
    JqueryDemoTools-用于整理jQueryDemo 分类: C# 公共资源 2014-12-02 16:50 223人阅读 评论(1) 收藏
    JqueryDemoTools-用于整理jQueryDemo 分类: C# 公共资源 2014-12-02 16:50 224人阅读 评论(1) 收藏
    visual studio2010复制粘贴源代码到Word时乱码问题 分类: C# 2014-11-28 09:25 686人阅读 评论(0) 收藏
    visual studio2010复制粘贴源代码到Word时乱码问题 分类: C# 2014-11-28 09:25 687人阅读 评论(0) 收藏
    不定义JQuery插件,不要说会JQuery 分类: JavaScript 2014-11-24 14:18 154人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4660382.html
Copyright © 2011-2022 走看看