by zhangxinxu from http://www. 一、看似偶然的東西實(shí)際是必然會發(fā)生的我大學(xué)時(shí)候在圖書館翻過一本很破舊的書,,講生物理論的,,主要內(nèi)容就是探討生命的產(chǎn)生是偶然還是必然。里面很多亞里士多德都看不懂的公式計(jì)算什么的,還有模擬原始地球環(huán)境出現(xiàn)了有機(jī)物的實(shí)驗(yàn)什么的 ,??傊瑫撌龅挠^點(diǎn)是:“在當(dāng)時(shí)的地球環(huán)境下,,生命的產(chǎn)生是必然的,!” 無數(shù)次機(jī)會的偶然條件、無數(shù)次化合物的相遇反應(yīng)等必定會產(chǎn)生有機(jī)物,,再有N多偶然,,有機(jī)物必然形成了有機(jī)體…… 這種理論類似于,你是個(gè)過馬路非常小心的人,,且你萬壽無疆,,除了怕被汽車撞。給你100萬年的壽命,,你最后必然還是被車撞死,。 如果以這種理論來看jQuery的出現(xiàn),結(jié)論也應(yīng)該是必然的,! 二,、需求、動力,、發(fā)展,、事物產(chǎn)生與jQuery的誕生一個(gè)成熟的東西顯然不是一口氣就出來的,所謂“一鏟子挖不了一口井”,,我想jQuery的原作者再天才,,也是循序漸進(jìn)過來的,如何個(gè)循序漸進(jìn)法,,我想,,很有可能就是需求驅(qū)動而產(chǎn)生的,好比上圖刀削面機(jī)器人,,據(jù)說現(xiàn)在已經(jīng)第八代了,! 1. gelElementById太長了 <button id="button">點(diǎn)擊我</button> <img id="image" src="xxx.jpg"> 于是,我的腳本可能就這樣: var button = document.getElementById("button") , image = document.getElementById("image") button.onclick = function() { image.style.display = "none"; }; 有何問題,?人幾乎都是天生的“懶惰者”,, var $ = function(id) { return document.getElementById(id); }; $("button").onclick = function() { $("image").style.display = "none"; }; 這里的 2. 我需要一個(gè)簡潔的暗號,就像“芝麻開門” $("button").onclick = function() { $("image1").style.display = "none"; $("image2").style.display = "none"; }; 好像又看見長長的重復(fù)的東西,, 這里每次隱藏都要 就是要變成下面的效果: $("button").onclick = function() { $("image1").hide(); $("image2").hide(); }; 3. 如何識別“芝麻開門”的暗號 哦,,擴(kuò)展,立馬想到了JS中的 HTMLElement.prototype.hide = function() {
this.style.display = "none";
};
上面代碼的demo地址應(yīng)該不會被人看到吧…… 雖然在身體上鉆了個(gè)窟窿插進(jìn)入了一個(gè)方法,,畢竟瀏覽器有有效果啊,切膚之痛就不算什么了,。但是,,我們是在泱泱天朝,很多IE6~IE8老頑固,,這些老東西不認(rèn)識 因此,,由于兼容性,我們需要想其他擴(kuò)展方法,。 4. 條條大路通羅馬,,此處不留爺,自有留爺處 var F = function() {};
F.prototype.hide = function() {
this?.style.display = "none";
};
new F().hide(); // 這個(gè)實(shí)現(xiàn)隱藏? 本文至少還有一半的內(nèi)容,,但是,,全文的最難點(diǎn)就在這里的,對 上面的代碼,,new F()您可以看做是
上面的引用來自這里,。什么意思呢?說白了就是,, 舉例說明: var F = function(id) {
return document.getElementById(id);
};
new F("image1") == document.getElementById("image1"); // true 說明看上去返回DOM對象,,實(shí)際確實(shí)就是DOM對象 var F = function(id) {
return id;
};
new F("image1") == "image1"; // false 說明看上去返回字符串值,,實(shí)際并不是字符串 回到上面天真的想法,。要想使用 因此,, var F = function(id) { this.element = document.getElementById(id); }; F.prototype.hide = function() { this.element.style.display = "none"; }; new F("image").hide(); // 看你還不隱藏 上面代碼的demo地址應(yīng)該不會被人看到吧…… 5. 我不喜歡太暴露 new F("image").hasOwnProperty("element"); // true 太暴露了,,我不喜歡~~ 如何隱藏?代碼如下: var F = function(id) { return this.getElementById(id); }; F.prototype.getElementById = function(id) { this.element = document.getElementById(id); return this; }; F.prototype.hide = function() { this.element.style.display = "none"; }; new F("image").hide(); // 看你還不隱藏 元素獲取方法放在 于是乎,,現(xiàn)在就沒有直接暴露的API了,。 上面代碼的demo地址應(yīng)該不會被人看到吧…… 6. 我不喜歡new, 我喜歡$ 好吧,,把 var $ = function(id) { return new F(id); }; 于是,上面的圖片隱藏的直接執(zhí)行代碼就是: $("image").hide(); 上面代碼的demo地址應(yīng)該不會被人看到吧…… IE6瀏覽器也是支持的哦,!是不是已經(jīng)有些jQuery的樣子啦,! 7. 你怎么就一種姿勢啊,人家都膩了誒 在IE8+瀏覽器中,,我們有選擇器API,, var F = function(selector, context) {
return this.getNodeList(selector, context);
};
F.prototype.getNodeList = function(selector, context) {
context = context || document;
this.element = context.querySelectorAll(selector);
return this;
};
var $ = function(selector, context) {
return new F(selector, context);
}; 此時(shí),,我們就可以使用各種選擇器了,例如,, 8. IE6/IE7腫么辦,? jQuery就使用了一個(gè)比較強(qiáng)大的選擇器框架- 8. 遍歷是個(gè)麻煩事 F.prototype.hide = function() { var i=0, length = this.element.length; for (; i<length; i+=1) { this.element[i].style.display = "none"; } }; 于是乎: $("img").hide(); // 頁面所有圖片都隱藏啦! 上面代碼的demo地址應(yīng)該不會被人看到吧…… 單純一個(gè) 因此,,急需一個(gè)遍歷包裝器元素的方法,,姑且叫做 于是有: F.prototype.each = function(fn) { var i=0, length = this.element.length; for (; i<length; i+=1) { fn.call(this.element[i], i, this.element[i]); } return this; }; F.prototype.hide = function() { this.each(function() { this.style.display = "none"; }); }; $("img").hide(); // 頁面所有圖片都隱藏啦! 上面代碼的demo地址應(yīng)該不會被人看到吧…… 9. 我不喜歡this.element, 可以去掉嗎,? F.prototype = { element: [NodeList], each: function() {}, hide: function() {} }
于是, F.prototype.init = function(selector, context) { var nodeList = (context || document).querySelectorAll(selector); this.length = nodeList.length; for (var i=0; i<this.length; i+=1) { this[i] = nodeList[i]; } return this; }; 此時(shí),, F.prototype.each = function(fn) { var i=0, length = this.length; for (; i<length; i+=1) { fn.call(this[i], i, this[i]); } return this; }; 我們也可以直接使用索引訪問包裝器中的DOM元素,。例如: 上面代碼的demo地址應(yīng)該不會被人看到吧…… 10. 我是完美主義者,,我特不喜歡F名稱,,可以換掉嗎? 這個(gè)…… 好吧,,想想其他辦法吧,。一步一步來,,那我把所有的 就有: 上圖代碼的demo地址應(yīng)該不會被人看到吧…… 顯然,運(yùn)行是OK的,。似乎也非常有jQuery的模樣了,,但是,實(shí)際上,,跟jQuery比還是有差別的,,有個(gè)較大的差別。如果是上圖代碼所示的JS結(jié)構(gòu),,則包裝器對象要擴(kuò)展新方法,,每個(gè)都需要再寫一個(gè)原型的。例如,,擴(kuò)展一個(gè) $.fn.prototype.attr = function() {
// ...
}; 又看到 腦子動一下就知道了,,把 $.fn.attr = function() {
// ...
}; 至此,就使用上講,,與jQuery非常接近了,。 但是,還有幾個(gè) F 怎么辦呢,,總不能就像下面這樣放著吧:var $ = function(selector, context) { return new F(selector, context); }; var F = function(selector, context) { return this.init(selector, context); }; $.fn = F.prototype; $.fn.init = function(selector, context) { // ... return this; }; $.fn.each = function(fn) { // ... }; $.fn.hide = function() { // ... }; 數(shù)學(xué)中,,我們都學(xué)過合并同類項(xiàng)。仔細(xì)觀察上面的的代碼: 于是,一番調(diào)整有: var $ = function(selector, context) { return new $.fn.init(selector, context); }; var F = function() { }; $.fn = F.prototype; $.fn.init = function(selector, context) { // ... return this; }; // ... 上面代碼顯然是有問題的, $.fn.init.prototype = $.fn 于是, 于是乎,大功告成,。慢著…… 上面明明還有殘留的 哦,那個(gè)啊,。 var $ = function(selector, context) { return new $.fn.init(selector, context); }; 上圖代碼的demo地址應(yīng)該不會被人看到吧…… 實(shí)際上,,如果你不是非得一個(gè) 至此,jQuery大核心已經(jīng)一步一步走完了,,可以看到,,所有的這些進(jìn)階都是根據(jù)需求、實(shí)際開發(fā)需要來的,,慢慢完善,,慢慢擴(kuò)充的! 11. 每個(gè)擴(kuò)展方法都要$.fn.xxxx, 好鬧心的來 $.fn.css = function() {}
$.fn.attr = function() {}
$.fn.data = function() {}
// ... 每個(gè)擴(kuò)展前面都有個(gè) 于是,jQuery搞了個(gè) $.fn.extend({
css: function() {},
attr: function() {},
data: function() {},
// ...
}); 12. $()不僅可以是選擇器字符串,,還可以是DOM 以下13~?都是完善啊,,補(bǔ)充啊,兼容性處理啊什么的,,沒有價(jià)值,,到此為止! 三,、排了很長隊(duì)的結(jié)束語網(wǎng)上也有其他一些介紹jQuery原理或機(jī)制的文章,,可能當(dāng)事人自己理解,而閱讀者本來就不懂,,說來說去,,越說越繞,可能更不懂了,。 jQuery是很優(yōu)秀,,好比身為靈長類的人類。但是,,其誕生顯然是從簡單開始的,。因此,要了解人類,,可以通過追溯其起源,。如果你是上帝,要讓你造一個(gè)人,,你會怎么造,,是一口氣出來?女媧造人還要捏泥人呢,!不妨從單細(xì)胞生物開始,,隨著自然進(jìn)化,淘汰,,自然而然,,就會出現(xiàn)人類,上帝他就是這么干的,。 jQuery的誕生也大致如此,,要想了解jQuery,可以試試踏著本文jQuery的成長足跡,,一點(diǎn)一點(diǎn)逐步深入,,您就會了解為何jQuery要這么設(shè)計(jì),它是如何設(shè)計(jì)的等,。 雖然,,內(nèi)容由淺及深,但是,其中涉及的原型以及 感謝您的閱讀至此,歡迎指出文章可能書寫不準(zhǔn)確的地方,,再次感謝,! 月底在百姓網(wǎng)有個(gè)小分享,演示文檔連個(gè)肉渣子還沒準(zhǔn)備呢,。因此,,未來一周休文。 原創(chuàng)文章,,轉(zhuǎn)載請注明來自張鑫旭-鑫空間-鑫生活[http://www.] (本篇完) 如果您覺得本文的內(nèi)容對您的學(xué)習(xí)有所幫助: 相關(guān)文章
標(biāo)簽: dom, extend, jQuery, prototype, querySelectorAll, this上下文, 原型, 繼承
|
|