-
立即調用表達式 任何庫與框架設計的第一個要點就是解決命名空間與變量污染的問題。jQuery就是利用了JavaScript函數作用域的特性,采用立即調用表達式包裹了自身的方法來解決這個問題。 jQuery的立即調用函數表達式的寫法有三種: 寫法1: (function(window, factory) { factory(window) }(this, function() { return function() { //jQuery的調用 } })) 可以看出上面的代碼中嵌套了2個函數,而且把一個函數作為參數傳遞到另一個函數中并且執行,這種方法有點復雜,我們簡化一下寫法: 寫法2: var factory = function(){ return function(){ //執行方法 } } var jQuery = factory(); 上面的代碼效果和方法1是等同的,但是這個factory有點變成了簡單的工廠方法模式,需要自己調用,不像是一個單例的jQuery類,所以我們需要改成“自執行”,而不是另外調用。 寫法3: (function(window, undefined) { var jQuery = function() {} // ... window.jQuery = window.$ = jQuery; })(window);查看全部
-
靜態與實例方法共享設計 jQuery在接口的設計: 遍歷方法: $(".aaron").each() //作為實例方法存在 $.each() //作為靜態方法存在 這是最常見的遍歷方法,第一條語句是給有指定的上下文調用的,就是(".aaron")獲取的DOM合集,第二條語句$.each()函數可用于迭代任何集合,無論是“名/值”對象(JavaScript對象)或數組。在迭代數組的情況下,回調函數每次都會傳遞一個數組索引和相應的數組值作為參數。本質上來說2個都是遍歷,那么我們是不是要寫2個方法呢? 我們來看看jQuery的源碼: jQuery.prototype = { each: function( callback, args ) { return jQuery.each( this, callback, args ); } } 實例方法取于靜態方法,換句話來說這是靜態與實例方法共享設計,靜態方法掛在jQuery構造器上,原型方法掛在哪里呢? 我們上節不是講了內部會劃分一個新的構造器init嗎?jQuery通過new原型prototype上的init方法當作構造器,那么init的原型鏈方法就是實例的方法了,所以jQuery通過2個構造器劃分2種不同的調用方式一種是靜態,一種是原型。 方法是共享的,并且實例方法取于靜態方法,2個構造器是完全隔離的 ,這個要如何處理? 看看jQuery給的方案: 畫龍點睛的一處init.prototype = jQuery.fn,把jQuery.prototype原型的引用賦給jQuery.fn.init.prototype的原型,這樣就把2個構造器的原型給關聯起來了。 ajQuery.fn = ajQuery.prototype = { name: 'aaron', init: function(selector) { this.selector = selector; return this; }, constructor: ajQuery } ajQuery.fn.init.prototype = ajQuery.fn查看全部
-
var $$ = ajQuery = function(selector) { this.selector = selector; return new ajQuery(selector); } 是一個死循環,為了避免死循環 var $$ = ajQuery = function(selector) { //把原型上的init作為構造器 return new ajQuery.fn.init( selector ); } init是ajQuery原型上作為構造器的一個方法,所以通過new ajQuery.fn.init( selector );之后,那么init的this就不再是aJQuery了,init的this就完全引用不到aJQuery的原型了,所以這里通過new把init方法與aJQuery給分離成2個獨立的構造器了.查看全部
-
jQuery為了避免出現這種死循環的問題,采取的手段是把原型上的一個init方法作為構造器 var $$ = ajQuery = function(selector) { //把原型上的init作為構造器 return new ajQuery.fn.init( selector ); } ajQuery.fn = ajQuery.prototype = { name: 'aaron', init: function() { console.log(this) }, constructor: ajQuery } 這樣確實解決了循環遞歸的問題,但是又問題來了,init是ajQuery原型上作為構造器的一個方法,那么其this就不是ajQuery了,所以this就完全引用不到ajQuery的原型了,所以這里通過new把init方法與ajQuery給分離成2個獨立的構造器。查看全部
-
分離構造器 通過new操作符構建一個對象,一般經過四步: A.創建一個新對象 B.將構造函數的作用域賦給新對象(所以this就指向了這個新對象) C.執行構造函數中的代碼 D.返回這個新對象 最后一點就說明了,我們只要返回一個新對象即可。其實new操作符主要是把原型鏈跟實例的this關聯起來,這才是最關鍵的一點,所以我們如果需要原型鏈就必須要new操作符來進行處理。否則this則變成window對象了。 我們來剖析下jQuery的這個結構,以下是我們常見的類式寫法: var $$ = ajQuery = function(selector) { this.selector = selector; return this } ajQuery.fn = ajQuery.prototype = { selectorName:function(){ return this.selector; }, constructor: ajQuery } var a = new $$('aaa'); //實例化 a.selectorName() //aaa //得到選擇器名字 首先改造jQuery無new的格式,我們可以通過instanceof判斷this是否為當前實例: var $$ = ajQuery = function(selector) { if(!(this instanceof ajQuery)){ return new ajQuery(selector); } this.selector = selector; return this } 但是注意千萬不要像下面這樣寫: var $$ = ajQuery = function(selector) { this.selector = selector; return new ajQuery(selector); } Uncaught RangeError: Maximum call stack size exceeded 這樣會無限遞歸自己,從而造成死循環并且溢出。查看全部
-
jQuery對象的構建如果在性能上考慮,所以就必須采用原型式的結構: jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); } jQuery.fn = jQuery.prototype = { init:function(){ return this }, jquery: version, constructor: jQuery, ……………… } var a = $() ; 使用原型結構,性能上是得到了優化,但是ajQuery類這個結構與目標jQuery的結構的還是有很大不一致: ? 沒有采用new操作符; ? return返回的是一個通過new出來的的對象 。查看全部
-
函數在充當類的構造器時,原型prototype是一個重要的概念。prototype是構造函數的一個屬性, 該屬性指向一個對象。而這個對象將作為該構造函數所創建的所有實例的基引用(base reference), 可以把對象的基引用想像成一個自動創建的隱藏屬性。 當訪問對象的一個屬性時, 首先查找對象本身, 找到則返回;若不, 則查找基引用指向的對象的屬性(如果還找不到實際上還會沿著原型鏈向上查找, 直至到根)。 只要沒有被覆蓋的話, 對象原型的屬性就能在所有的實例中找到。 類一: function ajQuery() { this.name = 'jQuery'; this.sayName = function(){ return this.name } var a = new ajQuery() var b = new ajQuery() var c = new ajQuery() 類二: function ajQuery() { this.name = 'jQuery' } ajQuery.prototype = { sayName: function() { return this.name } } var a = new ajQuery() var b = new ajQuery() var c = new ajQuery() 類一與類二產生的結構幾乎是一樣的,而本質區別就是:類二new產生的a、b、c三個實例對象共享了原型的sayName方法,這樣的好處節省了內存空間,類一則是要為每一個實例復制sayName方法,每個方法屬性都占用一定的內存的空間,所以如果把所有屬性方法都聲明在構造函數中,就會無形的增大很多開銷,這些實例化的對象的屬性一模一樣,都是對this的引用來處理。除此之外類一的所有方法都是拷貝到當前實例對象上。類二則是要通過scope連接到原型鏈上查找,這樣就無形之中要多一層作用域鏈的查找了。查看全部
-
如果我們需要同時使用jQuery和其他JavaScript庫,我們可以使用 $.noConflict()把$的控制權交給其他庫。舊引用的$ 被保存在jQuery的初始化; noConflict() 簡單的恢復它們。 通過類似swap交換的概念,先把之前的存在的命名空間給緩存起來,通過對比當前的命名空間達到交換的目的,首先,我們先判斷下當前的的$空間是不是被jQuery接管了,如果是則讓出控制權給之前的_$引用的庫,如果傳入deep為true的話等于是把jQuery的控制權也讓出去了。 如果不通過noConflict處理的話其后果可想而知,香噴噴的$大家都“覬覦已久”。查看全部
-
jQuery多庫共存處理 多庫共存換句話說可以叫無沖突處理。 總的來說會有2種情況會遇到: 1、$太火熱,jQuery采用$作為命名空間,不免會與別的庫框架或者插件相沖突。 2、jQuery版本更新太快,插件跟不上,導致不同版本對插件的支持度不一樣。 出于以上的原因,jQuery給出了解決方案–– noConflict函數。 引入jQuery運行這個noConflict函數將變量$的控制權讓給第一個實現它的那個庫,確保jQuery不會與其他庫的$對象發生沖突。 在運行這個函數后,就只能使用jQuery變量訪問jQuery對象。例如,在要用到$("aaron")的地方,就必須換成jQuery("aaron"),因為$的控制權已經讓出去了。 使用DEMO: jQuery.noConflict(); // 使用 jQuery jQuery("aaron").show(); // 使用其他庫的 $() $("aaron").style.display = ‘block’; 這個函數必須在你導入jQuery文件之后,并且在導入另一個導致沖突的庫之前使用。當然也應當在其他沖突的庫被使用之前,除非jQuery是最后一個導入的。 由于比較簡單,我們直接上代碼解說: Var _jQuery = window.jQuery, _$ = window.$; jQuery.noConflict = function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; };查看全部
-
一個是ready一個是load,這兩個到底有什么區別呢? ready與load誰先執行: 大家在面試的過程中,經常會被問到一個問題:ready與load那一個先執行,那一個后執行?答案是ready先執行,load后執行。 DOM文檔加載的步驟: 要想理解為什么ready先執行,load后執行就要先了解下DOM文檔加載的步驟: (1) 解析HTML結構。 (2) 加載外部腳本和樣式表文件。 (3) 解析并執行腳本代碼。 (4) 構造HTML DOM模型。//ready (5) 加載圖片等外部文件。 (6) 頁面加載完畢。//load 從上面的描述中大家應該已經理解了吧,ready在第(4)步完成之后就執行了,但是load要在第(6)步完成之后才執行。查看全部
-
回溯處理: .preObject() .end() .addBack()查看全部
-
jQuery插件的兩種開發方式: (1)掛的jQuery命名空間下人全局函數,也可稱為靜態方法; (2)jQuery對象級別人方法,即掛的jQuery原型下的方法,這樣通過選擇器獲取人jQuery對象實例也可以共享該方法。 接口:$.extend(target, [object1], [objectN]); 接口使用: jQuery.extend({ data: function() {}, removeData: function() {} }); jQuery.fn.extend({ data: function() {}, removeData: function() {} }); jQuery.extend調用的時候上下文指的是jQuery構造器,而jQuery.fn.extend調用人時候上下文指向的是jQuery構造器人實例對象了。查看全部
-
實現鏈式調用的原理是在方法內部返回當前這個實例對象this。 優點:能夠節省代碼量,提高代碼人效率,代碼看起來更簡潔。 缺點:所有對象的方法都返回this,就高不能餓自己的返回值,不一定適合所有場合。查看全部
-
通過原型傳遞,實現實例方法和靜態方法共享設計。查看全部
-
使用$.noConflict();讓出$的控制權,可以通過閉包隔離,將$轉為局部變量使用。查看全部
舉報
0/150
提交
取消