细说jQuery原型的创建和实现原理,并用实例简单模仿

     在解析jQuery实现机理之前,我们先总结一下几点知识,这些都是我学习路上遇到的坑,我跌倒过很多次,现在把它补上:

     1)自定义构造函数,如下例:

         function person(){
              this.name="aa";
           }
           person();
           console.log(window.name);//aa

  这个函数是为了证明全局环境下的执行上下文是window(全局)对象,如上例无意间会创建一个全局变量name,因为this指向window对象。其实不通过new构造,执行函数内部的“this.属性”会成为其父级对象域内的属性;通过new构造,函数执行上下文会变成一个空的上下文,这个上下文代表了新生成的实例。总言之,this指向当前调用它的对象,更精确地说,this指向它的执行上下文。

     2)利用对象[基本数据类型]格式创建的属性只能通过对象[基本数据类型]的格式访问;

     3)在函数的内部有函数定义时为了避免this指针的指向混乱,在首函数的内部声明"var self=this;",用self来表示此函数的this指针,避免与其他函数内部this指针混淆;

     现在来看jQuery的实现机制:

    以下是jQuery1.61内的代码:

var jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        return new jQuery.fn.init( selector, context, rootjQuery );
    },
    ...
    class2type = {};
     
jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    init: function(selector, context, rootjQuery){
    }
}
 
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

  提炼总结上面这段代码:jQuery.fn.init是个构造函数,因为jQuery.fn.init.prototype=jQuery.prototype,所以jQuery.fn.init的实例对象也是jQuery的实例对象,意指jQuery.fn.init构造的实例对象,可以访问jQuery.fn.init.prototype的属性及函数,也可以访问jQuery.prototype的属性及函数。

    现在我们来遵循这个思路写上这样的代码:

            //创建一个jquery构造函数
            function jQuery(selector){
                return new jQuery.fn.init(selector); //返回一个jQuery对象,可以访问jQuery.fn.init.prototype与jQuery.prototype中属性
            }
          
           
            //添加一个init函数给jQuery.fn
            jQuery.fn=jQuery.prototype={
                constructor:jQuery,
                init:function(selector){  //通过init构造函数可以保持生产选取到dom节点的对象
                     if(selector==="undefined"){this.length=0;return this;}//未选择
                     if(selector.nodeType==1){this[0]=selector;}else{this[0]=document.getElementById(selector);} //这里this[0]指创建此jQuery实例对象的属性0,且访问格式只能是此jQuery对象[0]
                      this.length=1;  //给jQuery对象添加一个length属性
                },
                css:function(name,value){
                      this[0].style[name]=value;
                      return this;  //链式调用 ,这里this指css()的调用者--jquery的实例对象,而不是css构造出来的实例对象,返回jQuery对象
                },
                hide:function(){
                      var self=this;
                      setTimeout(function(){
                        self[0].style.display="none"; //self[0]为选取的Dom节点对象
                      },2000);
                    
                      return this; //链式调用,通过jQuery原型的实例对象获取
                },
                float:function(position){
                      this[0].style.float=position;
                      return this; //链式调用,返回此时调用的jQuery对象
                }

            }
            //将jQuery原型赋给jQuery.fn.init的原型,让init可以生产jQuery的实例
            jQuery.fn.init.prototype=jQuery.prototype;

    我的注释写的可能有些乱,但作为学习的资料,我希望写的详细一点,通过我的注释和你的思考,我相信理解起来并不困难。

       需要说明的是,我这段代码只能实现对有id标签的元素的选取,并提供了改变位置和隐藏以及改变css样式的功能,下面用一段代码测试:

         <p >234</p>
         <script type="text/javascript">
          jQuery("qq").float("right").hide();
         </script>

  我这里,功能完全可以实现,不知道你的怎么样,如果有啥问题,你可以给我留言。