javascript框架设计读书笔记之种子模块


Posted in Javascript onDecember 02, 2014

1.命名空间

js里面的命名空间就是使用对象的属性来扩展的。比如,用户定义一个A对象,A对象下面有B属性和C属性,同时B属性和C属性又是对象。因此A={B:{},C:{}},这时用户就可以在B对象和C对象中定义一样的方法,属性了。因此B和C就属于不同的命名空间。我们调用B,C对象里面的方法,就可以通过A.B.like(),A.C.like()调用了。当然A属于window对象中的属性。

但是有一种情况,比如:boke.jsp页面引入了jquery.js以及prototype.js(他们都会在window对象中添加$属性),这时就出现了冲突的情况。

因此jquery.js里面就有了noConflict()处理冲突。执行流程:页面首先引入prototype,这时prototype会占有window的$属性,然后再引入jquery时,jquery会把之前window的$属性存放在_$中,然后自己使用$属性。这时,你可以通过$调用jquery的方法。当你现在不需要使用jquery而想使用prototype时,就可以调用$.noConflict(),这时$就会恢复成prototype对象。这时你就可以通过$使用prototype方法了。

var _$ =  window.$,_jQuery= window.jQuery;

noConflict:function(deep){

         
window.$ = _$;

   
if(deep)  window.jQuery = _jQuery;

        
return jQuery;    //返回值,你可以赋值给其他变量名,比如,chaojidan,这样你就可以通过chaojidan调用jQuery中的方法了。

}

2.对象扩展

命名空间对象有了,那我们需要扩展功能。比如:我需要把A对象的属性和方法全部复制到B对象中。我不用一个一个在B对象中去写代码。

function mix(target , source){

    var args =  [].slice.call(arguments),i=1,

         isCover = typeof args[args.length-1] =="boolean" ? args.pop():true;  //不写,默认为true,默认是覆盖。

   if(args.length == 1){                                      
target = !this.window? this:{};

//如果只有一个对象参数时,就扩展this对象。比如:我在A对象的context中调用mix(B),那么这时的this就是A,因此会把B的属性和方法添加到A对象中。但是如果是在window中调用mix(B),就会把B对象中的属性和方法添加到一个空的对象中,并返回这个空的对象,以防覆盖window对象中同名的属性和方法。(只有window对象拥有window属性)

      i =0;

 }

 while((source = args[i++])){


for(key in source){

                      if(isCover || !(key in target))   //如果覆盖,就直接赋值,如果不覆盖,先判断key是否存在目标对象中,如果存在,就不赋值



   {





target[key] = source[key];

                      }

           }

   }

   return target;

}

大公司面试官很喜欢问数组的查重,大家可以去看看,数组中的每项可以是对象,而对象A和对象B即便一样的属性和方法,但是也是不相等的。字符串和数字,比如123和"123"等,网上一搜,就能找到很全的方法。

3.数组化

浏览器下有很多类数组对象,arguments,document.forms,document.links,form.elements,document.getElementsByTagName,childNodes等(HTMLCollection,NodeList)。

还有一种特殊写法的自定义对象

var arrayLike = {

       0:"a",

       1:"b",

      length:2

}

此对象写法,就是jQuery对象的写法。

我们需要把上述的类数组对象转换成数组对象。

[].slice.call方法可以解决。但是旧版本IE下的HTMLCollection,NodeList不是Object的子类,不能使用[].slice.call方法。

因此我们可以重写一个slice方法。

A.slice = window.dispatchEvent  ? function(nodes,start,end){   return [].slice.call(nodes,start,end);      }

//如果window有dispatchEvent  属性就证明支持[].slice.call方法,能力检测。

                 :function(nodes,start,end){

                       var ret = [],n=nodes.length;



if(end == undefined  ||  typeof end === "number"  && isFinite(end)){   //&&优先级高于||,因此end没写,或者end是有限数字就进入

                                start = parseInt(start,10)  || 0;   //如果start不存在或者不是数字,则就赋值为0.

                                end = end == undefined ? n:parseInt(end,10);    //如果end不存在,则赋值为n.






if(start < 0)    start + = n;






if(end< 0)    end + = n;






if(end>n)    end  = n;






for(var i = start;i<end;i++){

                                      ret[i-start] = nodes[i];     //低版本IE使用数组赋值的形式

                                 }




}




return ret;

}

4.类型的判断

js五种简单数据类型有:null,undefined,boolean,number,string。

还有复杂的数据类型:Object,Function,RegExp,Date,自定义的对象,比如:Person等。

typeof一般用来判断boolean,number,string,instanceof一般用来判断对象类型。但它们都有缺陷。比如:firame里面的数组实例就不是父窗口的Array的实例,调用instanceof会返回false。(这题360校招时问过)。typeof new Boolean(true)     // "object"   ,包装对象。boolean,number,string三种包装对象,js高级程序编程里面有讲。

有很多人使用typeof document.all来判断是否为IE,其实这是很危险的,因为此属性谷歌和火狐也喜欢,所以在谷歌浏览器下出现了这个情况:typeof document.all    //undefined  但是,document.all    //HTMLAllCollection,用typeof判断是undefined,但是可以读取此属性值。

但是现在可以使用Object.prototype.toString.call方法判断类型。此方法可以直接输出对象内部的[[Class]].但IE8及以下的window对象不能使用此方法。可以使用   window == document  //  true      document == window  // false      IE6,7,8下。

nodeType     ( 1:元素 Element    2:属性 attribute     3:文本  Text      9:document)

jquery中判断类型使用的方法:

class2type ={}

jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(i,name){

        
class2type [ "[object " + name + "]"  ] = name.toLowerCase();


//class2type = {"[object Boolean]":boolean,"[object Number ]":number ,"[object String ]":string ,"[object Function ]":function ,"[object 

Array ]":array ......}


});


jQuery.type = function(obj){             //如果obj是null,undefined等,就返回字符串"null","undefined"。如果不是,就调用toString方法,如果可以调用就判断,出错就返回object(IE低版本下的window,Dom等ActiveXobject对象)


return obj == null ? String(obj)  : class2type [ toString.call(obj) ]  || "object";

}

5.domReady

js操作dom节点时,页面必须构建好dom树才行。因此,通常使用window.onload方法。但是onload方法是等所有资源加载结束后才会执行。而为了让页面能更快的响应用户的操作,我们只需要dom树构建完毕,就应该使用js操作。而不需要等待所有资源都加载结束(图片,flash)。

因此出现了DOMContentLoaded事件,Dom树构建完成后触发。但是旧版本IE不支持,因此就有了hack。

 if(document.readyState === "complete"){   //以防Dom文档加载完成后才加载js文件。这时通过此判断来执行fn方法(你要执行的方法)。因为文档加载完成后,document.readyState的值为complete

         setTimeout(fn);      //异步执行,可以让它后面的代码先执行。这里是jQuery里面的用法,可以不用理解。

}

else if(document.addEventListener){//支持DOMContentLoaded事件

            document.addEventListener("DOMContentLoaded",fn,false);   //冒泡

window.addEventListener("load",fn,false);   //以防DOM树构建好之后才加载js文件。这时不会触发DOMContentLoaded事件(已经触发结束了),只会触发load事件

}

else{

document.attachEvent("onreadystatechange",function(){//针对IE下的iframe安全,有时会优先onload执行,有时不会。


if(document.readyState ==="complete"){



fn();


}

});

window.attachEvent("onload",fn);   //总会起到作用,以防其他监听事件没获取到,这样至少可以通过onload事件触发fn方法。

var top = false;//看是否在iframe中

     try{//window.frameElement即为包含本页面的iframe或frame对象。没有则为null。

          top = window.frameElement == null && document.documentElement;

      }catch(e){}

     if(top && top.doScroll){  //如果没有iframe,并且是IE

            (function doScrollCheck(){

                     try{





top.doScroll("left");//IE下,如果Dom树构建好,就可以调用html的doScroll方法



 




}catch(e){

                            return setTimeout(doScrollCheck,50);  //如果还没构建好,则继续监听

                    }

                    fn();

            })

    }

}

fn方法中必须包含移除所有的绑定事件。

当然IE还可以使用script defer hack,原理就是:指定了defer的script会在DOM树构建完后才执行。但是这需要添加额外的js文件,很少在单独的库里面用到。

使用原理:在文档中添加script标签,并用script.src = "xxx.js",监听script的onreadystatechange事件,当this.readyState == "complete"时,就执行fn方法。

也就是说,DOM构建好之后,xxx.js才会执行,它的this.readyState才会变成complete。

以上便是javascript框架设计的第一章的读书笔记了,内容比较精简,方便大家更好的理解这章的基本内容。

Javascript 相关文章推荐
Mootools 1.2教程 Fx.Tween的使用
Sep 15 Javascript
Javascript 匿名函数及其代码模式原理
Mar 19 Javascript
js 父窗口控制子窗口的行为-打开,关闭,重定位,回复
Apr 20 Javascript
js 高效去除数组重复元素示例代码
Dec 19 Javascript
JavaScript中三种常见的排序方法
Feb 24 Javascript
Vue+Element使用富文本编辑器的示例代码
Aug 14 Javascript
Javascript中将变量转换为字符串的三种方法
Sep 19 Javascript
基于js中style.width与offsetWidth的区别(详解)
Nov 12 Javascript
解决Vue调用springboot接口403跨域问题
Sep 02 Javascript
vue实例的选项总结
Jun 09 Javascript
javascript实现京东快递单号的查询效果
Nov 30 Javascript
React 高阶组件HOC用法归纳
Jun 13 Javascript
推荐一个封装好的getElementsByClassName方法
Dec 02 #Javascript
CSS3,HTML5和jQuery搜索框集锦
Dec 02 #Javascript
JavaScript和CSS交互的方法汇总
Dec 02 #Javascript
HTML,CSS,JavaScript速查表推荐
Dec 02 #Javascript
javascript函数声明和函数表达式区别分析
Dec 02 #Javascript
javascript常用方法汇总
Dec 02 #Javascript
js时间日期格式化封装函数
Dec 02 #Javascript
You might like
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
2013/06/19 PHP
PHP程序员基本要求和必备技能
2014/05/09 PHP
ucenter通信原理分析
2015/01/09 PHP
PHP模板引擎Smarty之配置文件在模板变量中的使用方法示例
2016/04/11 PHP
PHP微信分享开发详解
2017/01/14 PHP
针对PHP开发安全问题的相关总结
2019/03/22 PHP
jquery 学习笔记一
2010/04/07 Javascript
JS onmousemove鼠标移动坐标接龙DIV效果实例
2013/12/16 Javascript
jQuery简单实现遍历数组的方法
2015/04/14 Javascript
javascript实现数组中的内容随机输出
2015/08/11 Javascript
angularjs表格ng-table使用备忘录
2016/03/09 Javascript
HTML5 实现的一个俄罗斯方块实例代码
2016/09/19 Javascript
一个炫酷的Bootstrap导航菜单
2016/12/28 Javascript
vue v-model表单控件绑定详解
2017/05/17 Javascript
详解angularJS自定义指令间的相互交互
2017/07/05 Javascript
jquery+css实现Tab栏切换的代码实例
2019/05/14 jQuery
pm2启动ssr失败的解决方法
2019/06/29 Javascript
vue项目创建步骤及路由router
2020/01/14 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
jQuery AJAX应用实例总结
2020/05/19 jQuery
原生JavaScript写出Tabs标签页的实例代码
2020/07/20 Javascript
Python Trie树实现字典排序
2014/03/28 Python
Python中实现常量(Const)功能
2015/01/28 Python
Django视图之ORM数据库查询操作API的实例
2017/10/27 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
Python如何使用k-means方法将列表中相似的句子归类
2019/08/08 Python
Django中使用haystack+whoosh实现搜索功能
2019/10/08 Python
Django调用支付宝接口代码实例详解
2020/04/04 Python
浅谈Python描述数据结构之KMP篇
2020/09/06 Python
澳大利亚领先的武术用品和健身器材供应商:SMAI
2019/03/24 全球购物
解释下面关于J2EE的名词
2013/11/15 面试题
期末考试动员演讲稿
2014/01/10 职场文书
中国古代史学名著《战国策》概述
2019/08/09 职场文书
Python django中如何使用restful框架
2021/06/23 Python
CKAD认证中部署k8s并配置Calico插件
2022/03/31 Servers
详解Python中*args和**kwargs的使用
2022/04/07 Python