@[toc] 轉載請註明出處 初識jQuery 為什麼要使用jQuery? 1.什麼是jquery? jQuery是js的一個庫,簡化了js代碼的書寫(註:jQuery語句中用逗號分隔各個css,因為一條css對應一個對象屬性,對象屬性之間是用逗號分隔而非分號) 舉例: 例1:簡化了獲取元素的語句 ...
目錄
@
轉載請註明出處
初識jQuery
為什麼要使用jQuery?
1.什麼是jquery?
jQuery是js的一個庫,簡化了js代碼的書寫(註:jQuery語句中用逗號分隔各個css,因為一條css對應一個對象屬性,對象屬性之間是用逗號分隔而非分號)
舉例:
例1:簡化了獲取元素的語句 + 設置樣式的書寫變得更加直觀好記
例2:jQuery解決了相容性問題
註:因為jQuery是js的一個庫,引入的時候就是一個js文件,所以,我們是可以用原生js代碼來修改jQuery文件的?
如何使用jQuery?
1.下載jQuery庫
壓縮版本compressed:體積小,方便網路傳輸;但不易於閱讀。多用於實際使用。
未壓縮版本uncompressed: 體積大,便於閱讀,多用於開發。
2.引入jQuery庫
本地引入:同js一樣,用script引入,服從目錄語法
網路引入:示例
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
jQuery與js載入模式不同
1.入口函數的載入模式不同:
- 原生js的window.onload會等到頁面元素及鏈接的資源都載入完畢才會執行
- jQuery的ready()等到頁面元素載入完畢就執行,不會等待其他資源載入
2.重覆為同一元素添加事件的不同
- 原生JS為同一元素添加多個事件,後添加的覆蓋先添加的
- jQuery為同一元素添加多個事件,後者不會覆蓋前者
jQuery入口函數的四種寫法
1.\$ (document).ready(function(){......});
2.\$ (function(){......});
3.第一種中的\$ 換成jQuery
4.第二種里的\$ 換成jQuery
我們遵循write less,do more的原則,推薦使用第二種寫法。
jQuery的訪問符衝突問題
1.jQuery訪問符衝突問題: jQuery框架與其他框架都使用了\$ 時,書寫代碼時,使用\$ 就會有衝突(後引進的框架覆蓋先引進的)。
2.解決辦法:
釋放訪問符\$ 的使用權,改為jQuery。例:
jQuery.noConflict();
jQuery(function(){......});
釋放\$ 使用權之後,就不能用\$ 編寫jQuery代碼了,會無效。
釋放操作必須在用jQuery編寫代碼之前。自定義新的訪問符。例:
var Q = jQuery.noConflict();
Q(function(){......});
jQuery核心函數和jQuery對象實質
1.jQuery核心方法是什麼?
jQuery的核心方法就是jQuery(),或者說\$ ().
2.jQuery核心方法接收的參數有哪些情況?
- 回調函數:\$ (callback());
執行回調函數,並返回一個jQuery對象
- 字元串選擇器:\$ ('.center');
返回一個jQuery對象,保存了找到的DOM元素
- 字元串代碼片段:\$ ('< p >我是P< /p >');
按照代碼片段創建元素,並返回一個包含該元素的jQuery對象(註意:該元素並未添加至文檔樹,需要用額外代碼來添加)
- DOM元素: \$ (document.getElementById('box'));
返回一個jQuery對象,保存了該DOM元素
3.jQuery對象詳解
jQuery方法框架結構分析:
框架:
仔細看我們就可以發現,這個框架只不過是兩個立即執行函數的嵌套:
外層的:(function (window,undefined){})(window)
內層的:var jQuery = (function (){})())
而在內層的IIFE中:- 先定義了內層函數(閉包)jQuery
- 接著令閉包jQuery的屬性fn與原型prototype都指向一個新建的字面量對象,該字面量對象中定義了屬性constructor,length等;也定義了許多函數,其中就包含了最核心的init函數.
- 然後,將init函數的原型prototype指向init所在的字面量對象.
- 最後將閉包jQuery返回給外層IIFE.
下圖為內層IIFE中定義的閉包jQuery的重要引用的分佈:
- 先定義了內層函數(閉包)jQuery
在後面的分析我們會知道--jQuery對象的實質就是jQuery.fn.init的實例,因此結合上圖,我們不難發現:
1.自定義的字面量對象就是init的原型對象
2.我們通過jQuery.fn.init.prototype或者jQuery.prototype均可訪問和修改init的原型
分析完內層,我們接著分析框架中的外層IIFE:
(1) 將內層IIFE的返回值(內層的jQuery函數)賦給外層變數jQuery
(2) 定義全局變數jQuery,\$ ,並將上一步jQuery的值賦給它們(jQuery()與\$ ()的效果相同的原因)
- jQuery對象的實質
jQuery對象就是jQuery方法的返回值,由上面的分析:
由代碼return new jQuery.fn.init(selector, context, rootjQuery);
可知,jQuery方法的返回值,即jQuery對象就是jQuery.fn.init的實例.
3.jQuery對象是一個偽數組對象
偽數組對象:
- 含有屬性length
- 另外含有length個屬性,這些屬性鍵名為0到length-1
4.使用jQuery與使用原生js有什麼區別麽?在jQuery中是否能使用原生js代碼呢?
- 首先,從概念上,我們知道jQuery是js的一個庫,我們下載和引入的jQuery文件尾碼都是".js".因此,概念上來說,jQuery本質就是js.
- 其次,jQuery從定義框架來看,他就是jQuery構造函數 + 自定義原型對象 + 自定義原型對象.init 這三個主要部分構成.
- 其三,jQuery方法的定義中,閉包jQuery的原型從Function(){}改為了自定義對象,那麼其原型鏈上就不再包含call函數.因此,不能通過其他對象調用jQuery的構造函數.也就是說:jQuery.call(obj,...)是錯誤的.
[jQuery對象原型鏈如下]:jQuery.fn.init實例-->jQuery.fn/jQuery.prototype-->Object.prototype
jQuery重要方法--參考資料
1.靜態jQuery.ready方法與實例.ready()方法
- jQuery的兩個插件擴展方法
- jQuery.extend(object):擴展jQuery構造函數本身,添所謂'靜態方法'(直接用構造函數名調用)
- jQuery.fn.extend(object):擴展jQuery原型對象,添加所謂'實例方法'(按習慣,用實例對象調用)
- 這兩個方法其實是同一個函數,只是this的值不同,導致了效果的不同.
這兩個方法定義時,是這麼一種形式:
jQuery.extend = jQuery.fn.extend = function() {
//實現代碼
}
- jQuery.extend(object):擴展jQuery構造函數本身,添所謂'靜態方法'(直接用構造函數名調用)
- 兩個ready方法
'靜態'jQuery.ready的定義:
源碼中的定義形式:
jQuery.extend({
ready:function (){}
});
說明:
(1).此方法返回一個類promise對象,當DOM載入就緒時,該對象變得可以解析.(即:當DOM載入就緒時,可以用該對象訪問其屬性,調用其方法等等)
(2).該方法的返回值會被jQuery.when,Promise.resolve()以及 .ready()方法中使用實例方法--.ready()
源碼定義如下:
jQuery.fn.ready = function( fn ) {
jQuery.ready.promise().done( fn );//當DOM載入就緒時,調用promise()方法並執行fn函數
return this;
};
說明: .ready(fn) 函數--當DOM載入就緒時執行fn函數jQuery.holdReady(hold)方法
說明:通過hold(取值:true/false)來延遲/取消延遲jQuery的ready事件.
2.'靜態'類型檢測方法
- jQuery.isFunction(obj)
- jQuery.isArray(obj)
- jQuery.isWindow(obj)
- jQuery.isNumeric(obj)
- jQuery.isEmptyObject(obj)
- jQuery.isPlainObject(obj)
3.'靜態'jQuery.each(obj,fn)方法
源碼定義: .each(obj,fn)方法是直接定義在jQuery原型上的
each: function( obj, callback ) {
var length, i = 0;
if ( isArrayLike( obj ) ) { //針對類數組
length = obj.length;
for ( ; i < length; i++ ) {
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break; //當回調函數返回false時,跳出整個迴圈
}
}
} else {
for ( i in obj ) { //針對enumerable不為false的一般對象
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break; //當回調函數返回false時,跳出整個迴圈
}
}
}
return obj;
}
源碼分析:
(1) 針對類數組對象,對每一個數字鍵值i,執行obj[i].callback(i,obj[i]).如果遇到某一項返回值為false,跳出迴圈,終止遍歷
(2) 針對一般對象,使用in操作符,對於每一個可遍歷鍵值i,執行obj[i].callback(i,obj[i]).如果遇到某一項返回值為false,跳出迴圈,終止遍歷
總結:
(1) 類數組不遍歷非數字鍵值屬性
(2) 一般對象不遍歷enumerable為false的屬性
(3) 一旦遍歷過程中某一次函數調用返回值為false,終止遍歷
(4) 整個.each的返回值為被遍歷的對象
4.'靜態' jQuery.map(elems,callback,arg)方法
源碼定義:
// arg is for internal usage only
map: function( elems, callback, arg ) {
var length, value,
i = 0,
ret = [];
// Go through the array, translating each of the items to their new values
if ( isArrayLike( elems ) ) { //針對類數組
length = elems.length;
for ( ; i < length; i++ ) {
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret.push( value );
} //將value中的值添加到數組末尾,並返回新的數組的長度
}
// Go through every key on the object,
} else {
for ( i in elems ) { //針對enumerable非false的一般對象
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret.push( value );
} //將value中的值添加到數組末尾,並返回新的數組長度
}
}
// Flatten any nested arrays
return concat.apply( [], ret );
} //Array.prototype.concat(合併數組,返回新數組) + Object.prototype.apply
源碼分析:
(1) 針對類數組對象,對每一個數字鍵值 i ,調用callback( elems[ i ], i, arg ),並將其中非null的返回值添加到數組ret中
(2) 針對一般對象,對每一個屬性名 i ,調用callback( elems[ i ], i, arg ),並將其中非null的返回值添加到數組ret中
總結:
(1) 類數組不遍歷非數字鍵值屬性
(2) 一般對象不遍歷enumerable為false的屬性
(3) 便利過程中,某一次函數調用返回值為null時,結果不計入ret中(我們可以靈活控制callback方法的返回值來達到我們想要的效果)
(4) 整個jQuery.map的返回值為被遍歷的對象被處理後所得到的數組ret