鋒利的Jquery解惑系列(一)------基本概念大鍋燉

聲明:雖然是基本概念但也是筆者通過一番學習才總結的這些文章,因此他不包括Jquery優缺點、特色、語法的介紹。javascript

概念一:jQuery對像與DOM對象html

  DOM(Document Object Model, 文檔對象模型)他能夠表示成數據結構的樹java

<html>
    <head></head>
    <body>
        <h1></h
    </body>
</html>

 就像上面表示html、head、body、h1都是DOM元素節點而且具備父、兄關係,能夠經過JS中的方法得到這些方法jquery

 var domOjb = document.getElementBy("id");程序員

  jQuery對象就是經過jQuery包裝DOM對象後產生的對象數據結構

  jQuery對象是jQuery獨有的,若是一個對象是jQuery對象,那麼就可使用jQuery裏的方法閉包

$("#foo").html()//得到id=foo的元素內的HTML代榪

   等價於:dom

document.getElementById("foo").innerHTML;

 二者獲取的對象是不一樣的,因此他們的方法也不能相互調用函數

  jQuery對象與DOM對象的相互轉換學習

var #cr = $("#cr");
var ce = $cr[0];

var $cr = $("#cr");
var cr = $cr.get(0);
var cr = document.getElementById("cr");
var $cr = $(cr);

概念二:閉包在插件中的應用

  關於閉包這個概念是困惑我最久的東西,$、jQuery、()、{}這些字符串的一開始的寫法是讓人非常費解,但願此次我可以說青楚,也能你們少走彎路。

閉包在插件開發過程是用的最多的,說白了他就有點相似java裏面的內類。

  在這裏能夠先補上JS閉包的概念:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html

在理解閉包之前.最好能先理解一下做用域鏈的含義,簡單來講,做用域鏈就是函數在定義的時候建立的,用於尋找使用到的變量的值的一個索引,而他內 部的規則是,把函數自身的本地變量放在最前面,把自身的父級函數中的變量放在其次,把再高一級函數中的變量放在更後面,以此類推直至全局對象爲止.當函數 中須要查詢一個變量的值的時候,js解釋器會去做用域鏈去查找,從最前面的本地變量中先找,若是沒有找到對應的變量,則到下一級的鏈上找,一旦找到了變 量,則再也不繼續.若是找到最後也沒找到須要的變量,則解釋器返回undefined.

  瞭解了做用域鏈,咱們再來看看js的內存回收機制,通常來講,一個函數在執行開始的時候,會給其中定義的變量劃份內存空間保存,以備後面的語句 所用,等到函數執行完畢返回了,這些變量就被認爲是無用的了.對應的內存空間也就被回收了.下次再執行此函數的時候,全部的變量又回到最初的狀態,從新賦 值使用.可是若是這個函數內部又嵌套了另外一個函數,而這個函數是有可能在外部被調用到的.而且這個內部函數又使用了外部函數的某些變量的話.這種內存回收 機制就會出現問題.若是在外部函數返回後,又直接調用了內部函數,那麼內部函數就沒法讀取到他所須要的外部函數中變量的值了.因此js解釋器在遇到函數定 義的時候,會自動把函數和他可能使用的變量(包括本地變量和父級和祖先級函數的變量(自由變量))一塊兒保存起來.也就是構建一個閉包,這些變量將不會被內 存回收器所回收,只有當內部的函數不可能被調用之後(例如被刪除了,或者沒有了指針),纔會銷燬這個閉包,而沒有任何一個閉包引用的變量纔會被下一次內存 回收啓動時所回收.

也就是說,有了閉包,嵌套的函數結構才能夠運做,這也是符合咱們的預期的.而後,閉包還有一些特性,卻每每讓程序員以爲很難理解.

看看下面一段代碼.

var result=[];
function foo(){
    var i= 0;
    for (;i<3;i=i+1){
        result[i]=function(){
            alert(i)
        }
    }
};
foo();
result[0](); // 3
result[1](); // 3
result[2](); // 3

 這段代碼中,程序員但願foo函數中的變量i被內部循環的函數使用,而且能分別得到他們的索引,而實際上,只能得到該變量最後保留的值,也就是說.閉包中所記錄的自由變量,只是對這個變量的一個引用,而非變量的值,當這個變量被改變了,閉包裏獲取到的變量值,也會被改變.

解決的方法之一,是讓內部函數在循環建立的時候當即執行,而且捕捉當前的索引值,而後記錄在本身的一個本地變量裏.而後利用返回函數的方法,重寫內部函數,讓下一次調用的時候,返回本地變量的值,改進後的代碼:

var result=[];
function foo(){
    var i= 0;
    for (;i<3;i=i+1){
        result[i]=(function(j){
            return function(){
                alert(j);
            };
        })(i);
    }
};
foo();
result[0](); // 0
result[1](); // 1
result[2](); // 2

保護 i變量的訪問,而且一直保存i在內存中,能夠一直增長-------這是閉包的主要做法

function a(){
 var i=0;
 function b(){
 alert(++i);
 }
 return b;
}

var c = a();
c();    //1
c();   //2

內部函數能夠訪問它們所在的外部函數中專聲明的全部局部變量、參數和聲明的其它內部函數,當其中一個這樣的內部函數在包含它們的外部函數以外被調用時,就會造成閉包

利用內部函數定義的臨時變量不會影響全局空間,因而就有下面這種寫法:

(function(){})();
定義了一個匿名函數function(){}而後用()括起來,接着用()來執行這個函數這就是典型的()()寫法

若是要傳參數能夠是:

(function($){
     $("div p").click("這裏用$可不會和其它插件衝突哦"); 
})(jQuery);
至關於:
function temp($){
    $("div p").click("這裏用$可不會和其它插件衝突哦"); 
}    
temp(jQuery)此時傳入jQuery對角做爲實際參數 
由於咱們實際傳入的參數是jQuery,因此形參$就是做爲jQuery對象的縮寫   

來看一段jQuery代碼:

((function($){
     var foo;
     var bar = function(){
        /*在匿名函數內部的函數均可以訪問foo,即便是在匿名函數的外部調用bar()的時候,
                  也能夠在  bar()的內部訪問到foo,可是匿名函數的外部直接訪問foo是作不到的*/
     }
     /*下面的語名讓匿名函數內部的函數bar()逃逸到全局可訪問的範圍內
     這樣就能夠在匿名函數的外部經過調用jQuery.BAR()來訪問內部定
     義的函數bar(),而且內部函數bar()也能訪問匿名函數內的變量foo*/
     $.BAR = bar;
})(jQuery)

 概念三:解決jQuery和其它庫的衝突

  一、jQuery庫在其它庫以後導入

    在其它庫和jQeury庫都被加載完畢後,能夠在任什麼時候候調用jQuery.noConflict()函數來將變量$的控制權移交給其它javaScript庫。

<p id="pp">隱藏元素</p>
<p>綁定單擊事件</p>
<!--引入prototype-->
<script src="lib/prototype.js" type="text/javascript"></script>
<!--引入jquery-->
<script src="../../scripts/jquery.js" type="text/javascript"></script>
<script>
    jQuery.noConflict(); //將變量$的控制權移交給prototype.js
    jQuery.(function){   //使用jquery
        jQuery("p").click(function(){
            alert(jQuery(this).text());
        });
    })
    $("pp").style.display="none"  //使用prototype.js隱藏元素
</script>

  此時,Jquery()函數做爲jQuery對像的製造工廠,還有加外一個做法

var $j=jquery.noConflict();  //自定義一個快捷方式
$j(function(){
    $j("p").click(function(){  //使用jquery,利用自定義快捷方式----$j
        alert($j(this).text());
    })
})
$("pp").style.display="none";    //使用prototype.js隱藏元素

  若是不想自定義這這些名稱,還想使用$而無論其它庫的$()方法,同時又不想與其餘庫相沖突,那麼可使用如下兩種解決方法

  一:

jQuery.noConflict();      //將變量$的控制權移交給prototype.js
jQuery(function($){        //使用jQuery設定頁面加載時執行的函數
    $("p").click(function(){  //在函數內部繼續使用$()方法。
        alert($(this).text());
    })
})
$("pp").style.display="none"   //使用prototype

  二:

jQuery.noConflict();      //將變量$的控制權讓渡給prototype.js
(function(($){            //定義匿名函數並設置形參$
    $(function(){            //匿名函數內部的$均爲jQuery
        $(function(){       //繼續使用$()方法;
            $("p").click(function(){
                alert($(this).text());
            });
        })
    }) 
})(jQuery)                    //執行匿名函數且傳遞實參jQuery
$("pp").style.display="none"   //使用prototype

  二、jQuery庫在其它庫以前導入

  若是jQuey庫在其它庫以前導入,那麼直接使用「jQuery」來作一些jQuery的工做。同時可使用$()方法做爲其它庫的快捷方式。這裏無需調用jQuery.noConflict()函數。

<p id="pp">隱藏元素</p>
<p>綁定單擊事件</p>
<!--先引入jquery-->
<script src="../../scripts/jquery.js" type="text/javascript"></script>
<!--引入prototype-->
<script src="lib/prototype.js" type="text/javascript"></script>
<script>
   jQuery(function(){     //直接使用jQuery,無需調用jQuery.noConflict();
        jQuery("p").click(function(){
            alert(jQuery(this).text());
        });
   })
   $("pp").style.display="none";    //使用prototype
</script>
相關文章
相關標籤/搜索