摘要:鏈?zhǔn)侥J酵ㄟ^在對象方法中將當(dāng)前對象返回,實現(xiàn)對同一個對象多個方法的鏈?zhǔn)秸{(diào)用。我們試著修改上面的函數(shù)然后執(zhí)行為什么會報錯呢因為這里,因為這里返回的指向的是,而不是的上并沒有這個方法。
??鏈?zhǔn)侥J剑?strong>通過在對象方法中將當(dāng)前對象返回,實現(xiàn)對同一個對象多個方法的鏈?zhǔn)秸{(diào)用。從而簡化對該對象的多個方法的多次調(diào)用,對該對象的多次引用。
??jquery是基于原型繼承,每個原型下的方法都返回當(dāng)前對象this,讓當(dāng)前對象一直在原型的最高層,這樣就可以實現(xiàn)鏈?zhǔn)秸{(diào)用。我們來試著創(chuàng)建一個模仿的鏈?zhǔn)秸{(diào)用的方法.
var jquery = function(seletor, context) { this.init(seletor, context) } jquery.fn = jquery.prototype = { //簡化寫法,再寫query.prototype就能省點力氣直接寫jquery.fn constructor: jquery, length: 0, init: function(seletor, context) { //定義上下文簡化版(*^__^*) if (context instanceof jquery) { //判斷上下文是否是jquery的實例 context = context[0] } else { context = context || document; //指定選擇范圍 //判斷上下文是否為字符串 context = typeof context == "string" ? querySelector(context) || context } this.context = context; //保存上下文 if (~seletor.indexOf("#")) { //判斷補碼是否為0,是則類,反之id選擇 this.length = 1; this[0] = context.querySelector(seletor); } else { //類選擇 var i = 0, selectArr = context.querySelectorAll(seletor), len = selectArr.length; for (; i < len; i++) { this[i] = selectArr[i] } this.length = len } return this; }, size: function() { return this.length } }
??我們在頁面上創(chuàng)建元素
12
var $cc = new jquery("#cc"); console.log($cc) //=>jquery {0: div.cc, 1: div.cc, length: 2} console.log($cc.size()) //=>2
??但是我們發(fā)現(xiàn)跟真正的jquery有很大差別, 真正的jquery沒有顯示的new一個構(gòu)造函數(shù)。我們試著修改上面的函數(shù)
var jquery = function(seletor, context) { return new jquery.fn.init(seletor, context) } //然后執(zhí)行 var $cc = jquery("#cc"); console.log($cc) //=>jquery {0: div.cc, 1: div.cc, length: 2} console.log($cc.size()) //=>$cc.size is not a function
??為什么會報錯呢?因為這里new jquery.prototype.init,因為這里返回的this指向的是init.prototype,而不是jquery.prototype,init的prototype上并沒有size這個方法。但是想一想,如果new jquery.prototype.init,返回的this指向jquery.prototype,那么不就能調(diào)用jquery.prototype的size方法嗎?真正的jquery源碼中是這樣的解決這個問題.
jquery.fn.init.prototype = jquery.fn
??加上這句話再次運行就不會報錯啦。
??真正的jquery有許多方法,有直接對jquery對象上掛載方法如:$.ajax,也有對選擇器擴(kuò)展的一些方法,如$(seletor).attr(),$(seletor).css...等等,也有許多jquery上的插件定義的方法。那么我們?nèi)绾蝸硗卣鼓兀吭谡嬲膉query中,如果寫過jquery插件或者了解過源碼,那么你會知道,是通過extend這個方法來拓展jquery一些方法。我們來動手試試吧!
jquery.extend = jquery.fn.extend = function() { var i = 1, len = arguments.length, target = arguments[0], //拷貝的目標(biāo)對象 deep, //是否深拷貝標(biāo)志 j; /*只有一個參數(shù)*/ if (i == len) { //如$.extend({a:1}) 運行后得到$.a =1 target = this i-- } if (typeof arguments[0] == "boolean") { //如果深拷貝,如$.extend(true,{},{a:1,b:{c:2}},{d:3}) deep = true i == 2 target = arguments[1] || {} } for (; i < len; i++) { for (j in arguments[i]) { var copy = arguments[i][j], //拷貝對象的值 src = target[i]; //拷貝到目標(biāo)對象的值 var type = {}.toString.call(copy) //深拷貝 if (deep && (type == "[object Object]" || type == "[object Array]")) { if (!Array.isArray(src)) { src = src || {} } else { src = src || [] } target[j] = $.extend(deep, src, copy) //遞歸循環(huán) } else if (copy != undefined) { target[j] = copy } } } return target }
??讓我們來動手試一試!運行效果
/*單個對象*/ var a = { a: 1 } jquery.extend(a) console.log(jquery.a) var b = { b: 2, c: { d: 3 }, } /*多個對象*/ var c = jquery.extend(a, b) console.log(c) c.c.d = 4 console.log(b.c.d) var e = { b: 2, c: { d: 3 }, } /*深拷貝*/ var f = jquery.extend(true, a, e) f.c.d = 4 console.log(e.c.d)
??運行成功后我們來為我們的jquery添加上方法,click,和attr
jquery.fn.extend({ on: (function(doc) { if (doc.addEventListener) { return function(type, fn) { var i = this.length - 1 for (; i >= 0; i--) { this[i].addEventListener(type, fn, false) } return this } } else if (doc.attachEvent) { return function(type, fn) { var i = this.length - 1; for (; i >= 0; i--) { this[i].attachEvent("on" + type, fn); } return this } } else { return function(type, fn) { var i = this.length - 1; for (; i >= 0; i--) { this[i]["on" + type] = fn } return this } } })(document), attr: function() { var arg = arguments, len = arg.length; if (len < 1) return false if (len == 1) { return this[0].getAttribute(arg[0]) } else if (len == 2) { for (var i in arg[0]) { for (var j = this.length - 1; j >= 0; j--) { this[j].setAttribute(arg[0], arg[1]) } } return this } } }) jquery(".cc").on("click", function() { console.log(this) }) jquery(".cc").attr("class","aa") console.log(jquery(".cc").attr("class"))
??以上就是javascript設(shè)計模式的鏈?zhǔn)侥J降膶W(xué)習(xí)喔。以上皆為demo版jquery代碼~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87257.html
摘要:單體模式在多種設(shè)計模式中,單體模式是最簡單,也是最基礎(chǔ)的設(shè)計模式。和之前說到的下劃線表示私用成員方法比較起來,最大的優(yōu)點就是可以創(chuàng)建真正的私用成員,使其不會在構(gòu)造函數(shù)之外被隨意修改。 單體模式 在多種Javascript設(shè)計模式中,單體模式是最簡單,也是最基礎(chǔ)的設(shè)計模式。它基礎(chǔ)到似乎不太像是一種設(shè)計模式,因為我們在編寫代碼的過程中隨時都會用到,并不需要過多思考,這是它簡單的一面。同時...
摘要:本回內(nèi)容介紹上一回,聊了聊狀態(tài)模式,并介紹了一下介一回,聊鏈?zhǔn)骄幊蹋M一下,再模擬一下封裝一個庫。這一回,主要聊了鏈?zhǔn)秸{(diào)用,模擬了,尤其是,希望大家能喜歡這次代碼分享。下一回,聊一聊的策略模式。 本回內(nèi)容介紹 上一回,聊了聊狀態(tài)模式(State),并介紹了一下vue.js;介一回,聊鏈?zhǔn)骄幊蹋M一下jQuery,再模擬一下underscore.js,封裝一個庫。 1. 鏈?zhǔn)秸{(diào)用 (...
摘要:創(chuàng)建全局對象構(gòu)造函數(shù)一個變量一個對象容器嵌套對象命名約定通常以全部大寫的方式來命名這個全局對象。在命名模式中,有一個全局對象,在沙箱模式中,有一個全局構(gòu)造函數(shù),我們這里命名為。 在javascript中,我們知道可以使用對象字面量或者構(gòu)造函數(shù)創(chuàng)建對象,但是如何優(yōu)雅地創(chuàng)建一個對象你卻不一定了解。 前人在踩過無數(shù)坑又填過無數(shù)坑之后,給我們總結(jié)了不同場景下的幾種對象創(chuàng)建模式: 命名空間模 ...
摘要:精讀原文介紹了學(xué)習(xí)源碼的兩個技巧,并利用實例說明了源碼學(xué)習(xí)過程中可以學(xué)到許多周邊知識,都讓我們受益匪淺。討論地址是精讀源碼學(xué)習(xí)如果你想?yún)⑴c討論,請點擊這里,每周都有新的主題,周末或周一發(fā)布。 1. 引言 javascript-knowledge-reading-source-code 這篇文章介紹了閱讀源碼的重要性,精讀系列也已有八期源碼系列文章,分別是: 精讀《Immer.js》源...
摘要:轉(zhuǎn)自阮一峰年月日上周,我整理了設(shè)計思想之理解篇。這樣的設(shè)計,使得讀取局部變量比讀取全局變量快得多。請看下面兩段代碼,第一段代碼是讀取全局變量第二段代碼是讀取局部變量第二段代碼讀取變量的時候,不用前往上一層作用域,所以要比第一段代碼快五六倍。 轉(zhuǎn)自:阮一峰 2011年8月4日 http://www.ruanyifeng.com/blo... 上周,我整理了https://segmentf...
閱讀 1459·2021-09-30 09:57
閱讀 1466·2021-09-09 09:33
閱讀 2220·2021-09-04 16:40
閱讀 1792·2021-09-01 10:50
閱讀 3237·2021-09-01 10:31
閱讀 2539·2019-08-30 15:56
閱讀 2970·2019-08-30 15:44
閱讀 3475·2019-08-29 17:29