拜讀一個開源框架,最想學到的就是設計的想法和實現的技巧。
廢話不多說,jquery這麼多年了分析都寫爛了,老早以前就拜讀過,
不過這幾年都是做行動端,一直御用zepto, 最近抽出點時間把jquery又給掃一遍
我也不會照本宣科的翻譯源碼,結合自己的實際經驗一起拜讀吧!
github上最新是jquery-master,加入了AMD規範了,我就以官方最新2.0.3為準
整體架構
jQuery框架的核心就是從HTML文件中匹配元素並對其執行操作、
例如:
$().find().css()
$().hide().html('....').hide().
從上面的寫法上至少可以發現2個問題
1. jQuery物件的建構方式
2 .jQuery方法的呼叫方式
分析一:jQuery的無new建置
JavaScript是函數式語言,函數可以實現類,類別就是物件導向程式設計中最基本的概念
var aQuery = function(selfpector, conpunction(self, context) { //建構子
}
aQuery.prototype = {
//原型
name:function(){},
var a = new aQuery();
a.name();
這是常規的使用方法,顯而易見jQuery不是這樣玩的
依照jQuery的書寫方式
複製程式碼
$(>
$().ready()
$(>
要實現這樣,那麼jQuery就要看成一個類,那麼$()應該是返回類的實例才對
所以把程式碼改一下:
var aQuery = function(selfpector, conpunction(self, context) { return new aQuery();
}
aQuery.prototype = {
name:function(){},
那麼如何回傳一個正確的實例?
在javascript中實例this只跟原型有關係
那麼可以把jQuery類別當作一個工廠方法來創建實例,把這個方法放到jQuery.prototye原型中
aQuery.prototype = {
init:function( name:function(){ },
age:function(){}
}
當執行aQuery() 傳回的實例:
問題來了init的this指向的是aQuery類,如果把init函數也當作一個建構器,那麼內部的this要如何處理?
複製程式碼
name: function() {},
age: 20
}
aQuery().age //18
這樣的情況下就出錯了,因為this只是指向aQuery類的,所以需要設計出獨立的作用域才行
jQuery框架分隔作用域的處理
jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );很明顯地透過實例init函數,每次都建構新的init實例對象,來分隔this,避免交互混淆
那麼既然都不是同一個物件那麼肯定又出現一個新的問題
複製程式碼
name: function() {},
age: 20
}
//Uncaught TypeError: Object [object Object] has no method 'name'
console.log(aQuery().name())
拋出錯誤,無法找到這個方法,所以很明顯new的init跟jquery類別的this分離了
怎麼存取jQuery類別原型上的屬性與方法?
做到既能隔離作用域還能使用jQuery原型物件的作用域呢,還能在傳回實例中存取jQuery的原型物件?
複製程式碼
程式碼如下:因為是引用傳遞所以不需要擔心這個循環引用的效能問題
複製程式碼
程式碼如下:aQuery.prototype.inin.prototype = aQuery. name()) //20
百度借網友的一張圖,方便直接理解:
fn解釋下,其實這個fn沒有什麼特殊意思,只是jQuery.prototype的引用
分析二:鍊式呼叫
DOM鍊式呼叫的處理:
1.節約JS代碼.
透過簡單地擴展原型方法並透過return this的形式來實現跨瀏覽器的鍊式呼叫。
利用JS下的簡單工廠模式,來將所有對於同一個DOM物件的操作指定同一個實例。
這個原理就超簡單了
複製程式碼
程式碼如下:
aQuery().init().name()分解
a = aQuery();a.init()
複製程式碼
程式碼如下:
aQuery.prototype = {
所以我們在需要鍊式的方法存取this就可以了,因為傳回目前實例的this,從而又可以存取自己的原型了
aQuery.init().name(>
aQuery.init().name(>
aQuery.init().name()
優點:節省程式碼量,提高程式碼的效率,程式碼看起來更優雅
最糟糕的是所有物件的方法回傳的都是物件本身,也就是說沒有回傳值,這不一定在任何環境下都適合。
Javascript是無阻塞語言,所以他不是沒阻塞,而是不能阻塞,所以他需要透過事件來驅動,非同步來完成一些本需要阻塞進程的操作,這樣處理只是同步鍊式,異步鍊式jquery從1.5開始就引入了Promise,jQuery.Deferred後期在討論。
分析三:外掛程式介面
jQuery的主體框架就是這樣,但是根據一般設計者的習慣,如果要為jQuery或者jQuery prototype添加屬性方法,同樣如果要提供給開發者對方法的擴展,從封裝的角度講是不是應該提供一個介面才對,字面就能看懂是對函數擴展,而不是看上去直接修改prototype.友好的用戶接口,
複製程式碼 程式碼如下:
jQuery.extend 對jQuery本身的屬性和方法進行了擴展
jQuery.fn.extend 對jQuery.fn的屬性和方法進行了擴展
透過extend()函數可以方便快速的擴充功能,不會破壞jQuery的原型結構
jQuery.extend = jQuery.fn.extend = function(){...}; 這個是連等,也就是2個指向同一個函數,怎麼會實作不同的功能呢?這就是this 力量了!
針對fn與jQuery其實是2個不同的對象,在之前有講述:
jQuery.extend 呼叫的時候,this是指向jQuery物件的(jQuery是函數,也是物件!),所以這裡擴充在jQuery上。
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {}, // 常见用法 jQuery.extend( obj1, obj2 ),此时,target为arguments[0]
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) { // 如果第一个参数为true,即 jQuery.extend( true, obj1, obj2 ); 的情况
deep = target; // 此时target是true
target = arguments[1] || {}; // target改为 obj1
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) { // 处理奇怪的情况,比如 jQuery.extend( 'hello' , {nick: 'casper})~~
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) { // 处理这种情况 jQuery.extend(obj),或 jQuery.fn.extend( obj )
target = this; // jQuery.extend时,this指的是jQuery;jQuery.fn.extend时,this指的是jQuery.fn
--i;
}
for ( ; i // Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) { // 比如 jQuery.extend( obj1, obj2, obj3, ojb4 ),options则为 obj2、obj3...
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) { // 防止自引用,不赘述
continue;
}
// Recurse if we're merging plain objects or arrays
// 如果是深拷贝,且被拷贝的属性值本身是个对象
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) { // 被拷贝的属性值是个数组
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else { 被拷贝的属性值是个plainObject,比如{ nick: 'casper' }
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
deep, clone, copy ); // 遞迴~
// Don't bring in undefined values
defined
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
總結:
透過new jQuery.fn.init() 建構一個新的對象,擁有init建構器的prototype原型物件的方法
透過改變prorotype指標的指向,讓這個新的物件也指向了jQuery類別的原型prototype
所以這樣建構出來的物件就延續了jQuery.fn原型定義的所有方法了

实现方法:1、用“$("img").delay(毫秒数).fadeOut()”语句,delay()设置延迟秒数;2、用“setTimeout(function(){ $("img").hide(); },毫秒值);”语句,通过定时器来延迟。

修改方法:1、用css()设置新样式,语法“$(元素).css("min-height","新值")”;2、用attr(),通过设置style属性来添加新样式,语法“$(元素).attr("style","min-height:新值")”。

区别:1、axios是一个异步请求框架,用于封装底层的XMLHttpRequest,而jquery是一个JavaScript库,只是顺便封装了dom操作;2、axios是基于承诺对象的,可以用承诺对象中的方法,而jquery不基于承诺对象。

增加元素的方法:1、用append(),语法“$("body").append(新元素)”,可向body内部的末尾处增加元素;2、用prepend(),语法“$("body").prepend(新元素)”,可向body内部的开始处增加元素。

在jquery中,apply()方法用于改变this指向,使用另一个对象替换当前对象,是应用某一对象的一个方法,语法为“apply(thisobj,[argarray])”;参数argarray表示的是以数组的形式进行传递。

删除方法:1、用empty(),语法“$("div").empty();”,可删除所有子节点和内容;2、用children()和remove(),语法“$("div").children().remove();”,只删除子元素,不删除内容。

去掉方法:1、用“$(selector).removeAttr("readonly")”语句删除readonly属性;2、用“$(selector).attr("readonly",false)”将readonly属性的值设置为false。

on()方法有4个参数:1、第一个参数不可省略,规定要从被选元素添加的一个或多个事件或命名空间;2、第二个参数可省略,规定元素的事件处理程序;3、第三个参数可省略,规定传递到函数的额外数据;4、第四个参数可省略,规定当事件发生时运行的函数。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。