<script>
  (function(w){
        //工厂
        function jQuery(selector, context){
            return new jQuery.fn.init(selector, context);
        }
        //给原型提供一个简写方式
        jQuery.fn = jQuery.prototype = {

        };
        //init才是jQuery中真正的构造函数
        var init = jQuery.fn.init = function(selector, context){

        };
        //把构造函数的原型,替换为jQuery工厂的原型
        //这么做的目的是为了实现jQuery的插件机制,让外界可以通过jQuery方便的进行扩展

        //构造函数的原型 == new出来的这个实例jQuery.fn =  jQuery.prototype 这样就实现了原型继承,可以在$ 对象上面封装自己的方法。
        init.prototype = jQuery.fn;
        w.jQuery = w.$ = jQuery;
    }(window));
</script>

1.jQuery借助了沙箱模式,其实整个jQuery包中的代码就是一个自执行函数,并且把window对象作为参数传递了过去。

  2.jQuery函数只是一个工厂,真正的构造函数时jQuery.fn.init( )

  3.把init的原型对象替换为jQuery.fn,其实也就是替换为了jQuery这个函数自己的原型对象,也就是jQuery.prototype,这么做的目的是为了实现插件机制,让外界可以通过jQuery方便的进行扩展。

  比如,我们要做一个对话框插件,就可以这么做:  

jQuery.fn.jqAlert = function(msg){
    alert(msg);
}

这样一个简单的jq插件就做好了,用的时候只需要调用:  

$().jqAlert('aaa');

 jQuery 与 jQuery.fn
在JQuery源码中,JQuery()的实现方式:

jQuery = function( selector, context ) {
     return new jQuery.fn.init( selector, context, rootjQuery );
 }

可以看到内部返回了一个jQuery.fn.init对象,用这种方式创建DOM对象的好处是隐藏了new的过程,使用 jQuery(‘#id’) 创建对象更加简洁,而不是 new jQuery(‘#id’) 。

jQuery.fn.init()函数实际是封装了查询DOM节点的原生接口,下面是init()的简洁版实现,JQuery中的实现复杂的多,还要考虑浏览器兼容性问题。

jQuery.fn = jQuery.prototype = {
    init: function(selector, context){
        var nodeList = (context || document).querySelectorAll(selector);
        this.length = nodeList.length;
        for (var i=0; i<this.length; i+=1) {
            this[i] = nodeList[i];    
        }
        return this;
    },

    each:function(){...}
    ...
}
//可以看到init()函数中将DOM节点赋值给了自己this[i] = nodeList[i],因此返回的init对象是一个类数
//组,包含了DOM节点列表,还包括一些其他的方法。
new出来的实例,这时候构造函数被执行,执行的时候传入相应的参数,
同时上下文的this会被指定为这个新的实例。
在不传递任何参数的情况下,new foo == new foo(),
如果构造函数返回了一个对象,那么这个返回的对象会取代new出来的结果,
如果构造函数没有返回对象,那么new出来的结果为新创建出来的对象
//this 就是$或者Jquery的类数组对象,里面包含了一些DOM节点列表,和一些方法


另外!!

经常在JQuery插件中发现一个问题,为什么方法返回的都是return this.each()

jQuery.fn.test= function(){ 
   this.css("background","#ff0");//因为调用对象是JQuery对象,这里面的this为jquery对象,而不是dom对象 
   return this.each(function(){  
          alert("this"+this+this.innerHTML); //each方法循环中的this为dom对象。 
   }); 
};
这里就要说到JQuery的一大特性,链式调用。

<div id="color">
    <p id="c1">1111</p>
	<p id="c2">2222</p>
	<p id="c3">3333</p>
</div>
 
<script type="text/javascript">
 
$("#color").find('#c1').css("color","red").next().css("color","blue").next().css("font-size","20px");
 
</script>
JQuery中的大多方法,返回的都是调用者本身,所以我们可以通过一条语句完成很多的操作。作为JQuery插件同时也要满足这点,所以我们也要返回一个JQuery对象。

可以看到init()函数中将DOM节点赋值给了自己this[i] = nodeList[i],因此返回的init对象是一个类数组,包含了DOM节点列表,还包括一些其他的方法。

其中 jQuery.fn = jQuery.prototype 则可以隐藏prototype属性,在后面为jQuery添加新方法时可以使用

jQuery.fn.each = function(){...}
 jQuery.fn.map  = function(){...}
 但是new jQuery.fn.init()中返回this,即init对象,此时init对象上并没有添加任何方法,于是:jQuery.fn.init.prototype = jQuery.fn;
 这样init对象继承了jQuery.fn中的所有方法,就可以愉快地使用了。jQuery.extend
 jQuery中还使用了大量extend({…})jQuery.extend = jQuery.fn.extend = function(){..}

该函数主要目的是简化添加扩展函数的过程:

例如:

jQuery.fn.each = function(){...}
 jQuery.fn.map  = function(){...}
 jQuery.fn.css  = function(){...}
 可以简化为jQuery.fn.extend({
     each:function(){...},
     map:function(){...},
     css:function(){...},
 })
 而jQuery.extend 和 jQuery.fn.extend区别像是一个静态函数,一个实例函数,前者使用方法为:jQuery.extend({
     isWindow: function( obj ) {
         return obj != null && obj == obj.window;
     }
 })jQuery.isWindow(window)  //true

而后者

jQuery.fn.extend({
     addClass: function() {...}
 })jQuery('#img').addClass('small')