JQuery披了一层外衣

jquery是一个轻量级的JS框架,它披了一件外衣,将自己给隐藏了起来。

(function( window, undefined ) { /* 源码内容 */ })
( window );

使用闭包技术,隐藏所有的局部变量,可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行。下面就是一个闭包的使用,实现了一个技术功能,保护内部变量,只有通过函数才可以对变量操作。

<script>
var aa=(function(){
 var count = 0;
 alert(count);//闭包中的一个重要的关键点是自我调用,运行时只运行一次,这里可对count这个变量做初始化
 return function() {
  count=count+1;
  return count;
 }
})();
aa();
aa();
alert(aa());
</script>

如何全局使用

jquery将自己声明的变量全部都用外衣遮盖起来了,而我们平时使用的Jquery和$,却是真真实实的全局变量,这个是从何而来,谜底就在jquery的某一行代码,一般是在文件的末尾。

<script>
(function(window,undefined){
 var jquery= function(selector) {
  return new jquery.fn.init(selector);
 };
  jquery.fn = jquery.prototype = {
         init:function(selector){
                 this.obj = window.document.getElementById(selector);
                 return this;
         }
     };
 jquery.method1 = function() {
  alert("hello");
 }  
 window.jquery=window.$=jquery;//将对象交给window的全局变量$或者是jquery
})(window);
$.method1();
</script>

 JQuery利器:Selector

jquery的最核心的功能就是选择器。而选择器简单理解的话,其实就是在DOM文档中,寻找一个DOM对象的工具。

首先我们进入jquery源码中,可以很容易的找到jquery对象的声明,看过以后会发现,原来我们的jquery对象就是init对象。

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

jQuery其实就是将DOM对象加了一层包裹,而寻找某个或者若干个DOM对象是由sizzle选择器负责的,它的官方地址是http://sizzlejs.com/,有兴趣的猿友可以去仔细研究下这个基于CSS的选择器。

下面截取的一个jQuery对象的属性和方法截图,方法这里就不提了,对于属性来说,我们最需要关注的只有一个属性,就是[0]属性,[0]其实就是原生的DOM对象。

jquery闭包写法页面如何引用 jquery闭包原理_jQuery

很多时候,我们在jQuery和DOM对象之间切换时需要用到[0]这个属性。从截图也可以看出,jQuery对象其实主要就是把原生的DOM对象存在了[0]的位置,并给它加了一系列简便的方法。这个索引0的属性我们可以从一小段代码简单的看一下它的由来,下面是init方法中的一小段对DOMElement对象作为选择器的源码。

if ( selector.nodeType ) {
 /* 可以看到,这里将DOM对象赋给了jQuery对象的[0]这个位置 */
        this.context = this[0] = selector;
        this.length = 1;
        return this;
    }

这一小段代码可以在jquery源码中找到,它是处理传入的选择参数是一个DOM对象的情况。可以看到,里面很明显的将jQuery对象索引0的位置以及context属性,都赋予了DOM对象。

jquery保证加载完成后再执行的ready

实现类似jquery的ready方法的效果我们是可以简单做到的,它的实现原理就是,维护一个函数数组,然后不停的判断DOM是否加载完毕,倘若加载完毕就触发所有数组中的函数。

jquery的扩展实现

jquery的extend方法的原版形式,jquery.extend(deep,target,source1,source2......)

以及 *jquery.fn.extend(deep,target,source1,source2......)。

*参数详解:

*deep:boolean类型,意为是否要深度拷贝

*target:Object类型,意为要扩展的目标对象

*source1:Object类型,意为被扩展的资源对象

*source2....:与source1相同,理论上可以有无限个

扩展$

$.extend(
{
testExtend:function(){
            alert('extend success');
        } } );

给对象进行扩展

var targetFn = {};//目标对象    
//此处targetFn将作为目标对象扩展
    $.fn.extend(targetFn,
      {
        testExtend:function(){
            alert('extend success');
        }
      }

    );
another:
var me = { 
name:"hill", 
sex:"man", //注意,这里我的女朋友,我的属性,也是一个对象
        girlFriend:{
            name:"secret",
            sex:"woman"
        }
    };//下面首先采用非深度拷贝的方式对我进行扩展
$.extend(me,
{
work:"programmer",//扩展我的工作为程序员
            girlFriend:{
                work:"rich"//扩展我女朋友的职业为富婆,这是不是若干人群的梦想
            }
        }
    );

/* *是不是发现我女朋友的名字和性别都未知了,这是因为在非深度拷贝的情况下,如 *果属性为对象,将会被扩展的属性值直接覆盖掉,也就是原来的属性name和sex会被直接覆盖,即name和sex会被work覆盖 */

如果换成深度扩展,就没有问题了

$.extend(
true,//深度拷贝
me, 
{ work:"programmer",//依然扩展我的工作为程序员
            girlFriend:{
                name:"secret",//当有相同属性名的时候会被覆盖
                work:"manager"//当有多出的属性名的时候会被扩展,扩展我女朋友的职业为经理
            }
        }
    );