by zhangxinxu from http://www. 一、看似偶然的東西實(shí)際是必然會(huì)發(fā)生的我大學(xué)時(shí)候在圖書館翻過一本很破舊的書,講生物理論的,主要內(nèi)容就是探討生命的產(chǎn)生是偶然還是必然。里面很多亞里士多德都看不懂的公式計(jì)算什么的,還有模擬原始地球環(huán)境出現(xiàn)了有機(jī)物的實(shí)驗(yàn)什么的 這種理論類似于,你是個(gè)過馬路非常小心的人,且你萬壽無疆,除了怕被汽車撞。給你100萬年的壽命,你最后必然還是被車撞死。 如果以這種理論來看jQuery的出現(xiàn),結(jié)論也應(yīng)該是必然的! 二、需求、動(dòng)力、發(fā)展、事物產(chǎn)生與jQuery的誕生一個(gè)成熟的東西顯然不是一口氣就出來的,所謂“一鏟子挖不了一口井”,我想jQuery的原作者再天才,也是循序漸進(jìn)過來的,如何個(gè)循序漸進(jìn)法,我想,很有可能就是需求驅(qū)動(dòng)而產(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è)簡潔的暗號(hào),就像“芝麻開門” $("button").onclick = function() { $("image1").style.display = "none"; $("image2").style.display = "none"; }; 好像又看見長長的重復(fù)的東西, 這里每次隱藏都要 就是要變成下面的效果: $("button").onclick = function() { $("image1").hide(); $("image2").hide(); }; 3. 如何識(shí)別“芝麻開門”的暗號(hào) 哦,擴(kuò)展,立馬想到了JS中的 HTMLElement.prototype.hide = function() {
this.style.display = "none";
};
上面代碼的demo地址應(yīng)該不會(huì)被人看到吧…… 雖然在身體上鉆了個(gè)窟窿插進(jìn)入了一個(gè)方法,畢竟瀏覽器有有效果啊,切膚之痛就不算什么了。但是,我們是在泱泱天朝,很多IE6~IE8老頑固,這些老東西不認(rèn)識(shí) 因此,由于兼容性,我們需要想其他擴(kuò)展方法。 4. 條條大路通羅馬,此處不留爺,自有留爺處 var F = function() {};
F.prototype.hide = function() {
this?.style.display = "none";
};
new F().hide(); // 這個(gè)實(shí)現(xiàn)隱藏? 本文至少還有一半的內(nèi)容,但是,全文的最難點(diǎn)就在這里的,對(duì) 上面的代碼,new F()您可以看做是
上面的引用來自這里。什么意思呢?說白了就是, 舉例說明: var F = function(id) {
return document.getElementById(id);
};
new F("image1") == document.getElementById("image1"); // true 說明看上去返回DOM對(duì)象,實(shí)際確實(shí)就是DOM對(duì)象 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)該不會(huì)被人看到吧…… 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)該不會(huì)被人看到吧…… 6. 我不喜歡new, 我喜歡$ 好吧,把 var $ = function(id) { return new F(id); }; 于是,上面的圖片隱藏的直接執(zhí)行代碼就是: $("image").hide(); 上面代碼的demo地址應(yīng)該不會(huì)被人看到吧…… IE6瀏覽器也是支持的哦!是不是已經(jīng)有些jQuery的樣子啦! 7. 你怎么就一種姿勢(shì)啊,人家都膩了誒 在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)該不會(huì)被人看到吧…… 單純一個(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)該不會(huì)被人看到吧…… 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)該不會(huì)被人看到吧…… 10. 我是完美主義者,我特不喜歡F名稱,可以換掉嗎? 這個(gè)……
就有: 上圖代碼的demo地址應(yīng)該不會(huì)被人看到吧…… 顯然,運(yùn)行是OK的。似乎也非常有jQuery的模樣了,但是,實(shí)際上,跟jQuery比還是有差別的,有個(gè)較大的差別。如果是上圖代碼所示的JS結(jié)構(gòu),則包裝器對(duì)象要擴(kuò)展新方法,每個(gè)都需要再寫一個(gè)原型的。例如,擴(kuò)展一個(gè) $.fn.prototype.attr = function() {
// ...
}; 又看到 腦子動(dòng)一下就知道了,把 $.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 于是, 于是乎,大功告成。慢著…… 上面明明還有殘留的
var $ = function(selector, context) { return new $.fn.init(selector, context); }; 上圖代碼的demo地址應(yīng)該不會(huì)被人看到吧…… 實(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è)人,你會(huì)怎么造,是一口氣出來?女媧造人還要捏泥人呢!不妨從單細(xì)胞生物開始,隨著自然進(jìn)化,淘汰,自然而然,就會(huì)出現(xiàn)人類,上帝他就是這么干的。 jQuery的誕生也大致如此,要想了解jQuery,可以試試踏著本文jQuery的成長足跡,一點(diǎn)一點(diǎn)逐步深入,您就會(huì)了解為何jQuery要這么設(shè)計(jì),它是如何設(shè)計(jì)的等。 雖然,內(nèi)容由淺及深,但是,其中涉及的原型以及 感謝您的閱讀至此,歡迎指出文章可能書寫不準(zhǔn)確的地方,再次感謝! 月底在百姓網(wǎng)有個(gè)小分享,演示文檔連個(gè)肉渣子還沒準(zhǔn)備呢。因此,未來一周休文。 原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明來自張?chǎng)涡?鑫空間-鑫生活[http://www.] (本篇完) 如果您覺得本文的內(nèi)容對(duì)您的學(xué)習(xí)有所幫助: 相關(guān)文章
標(biāo)簽: dom, extend, jQuery, prototype, querySelectorAll, this上下文, 原型, 繼承
|
|