摘要:链式模式通过在对象方法中将当前对象返回,实现对同一个对象多个方法的链式调用。我们试着修改上面的函数然后执行为什么会报错呢因为这里,因为这里返回的指向的是,而不是的上并没有这个方法。
链式模式:通过在对象方法中将当前对象返回,实现对同一个对象多个方法的链式调用。从而简化对该对象的多个方法的多次调用,对该对象的多次引用。
jquery是基于原型继承,每个原型下的方法都返回当前对象this,让当前对象一直在原型的最高层,这样就可以实现链式调用。我们来试着创建一个模仿的链式调用的方法.
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
}
}
我们在页面上创建元素
1
2
var $cc = new jquery("#cc");
console.log($cc) //=>jquery {0: div.cc, 1: div.cc, length: 2}
console.log($cc.size()) //=>2
但是我们发现跟真正的jquery有很大差别, 真正的jquery没有显示的new一个构造函数。我们试着修改上面的函数
var jquery = function(seletor, context) {
return new jquery.fn.init(seletor, context)
}
//然后执行
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,那么不就能调用jquery.prototype的size方法吗?真正的jquery源码中是这样的解决这个问题.
jquery.fn.init.prototype = jquery.fn
加上这句话再次运行就不会报错啦。
真正的jquery有许多方法,有直接对jquery对象上挂载方法如:$.ajax,也有对选择器扩展的一些方法,如$(seletor).attr(),$(seletor).css...等等,也有许多jquery上的插件定义的方法。那么我们如何来拓展呢?在真正的jquery中,如果写过jquery插件或者了解过源码,那么你会知道,是通过extend这个方法来拓展jquery一些方法。我们来动手试试吧!
jquery.extend = jquery.fn.extend = function() {
var i = 1,
len = arguments.length,
target = arguments[0], //拷贝的目标对象
deep, //是否深拷贝标志
j;
/*只有一个参数*/
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]; //拷贝到目标对象的值
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) //递归循环
} 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设计模式的链式模式的学习喔。以上皆为demo版jquery代码~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87257.html
摘要:单体模式在多种设计模式中,单体模式是最简单,也是最基础的设计模式。和之前说到的下划线表示私用成员方法比较起来,最大的优点就是可以创建真正的私用成员,使其不会在构造函数之外被随意修改。 单体模式 在多种Javascript设计模式中,单体模式是最简单,也是最基础的设计模式。它基础到似乎不太像是一种设计模式,因为我们在编写代码的过程中随时都会用到,并不需要过多思考,这是它简单的一面。同时...
摘要:本回内容介绍上一回,聊了聊状态模式,并介绍了一下介一回,聊链式编程,模拟一下,再模拟一下封装一个库。这一回,主要聊了链式调用,模拟了,尤其是,希望大家能喜欢这次代码分享。下一回,聊一聊的策略模式。 本回内容介绍 上一回,聊了聊状态模式(State),并介绍了一下vue.js;介一回,聊链式编程,模拟一下jQuery,再模拟一下underscore.js,封装一个库。 1. 链式调用 (...
摘要:创建全局对象构造函数一个变量一个对象容器嵌套对象命名约定通常以全部大写的方式来命名这个全局对象。在命名模式中,有一个全局对象,在沙箱模式中,有一个全局构造函数,我们这里命名为。 在javascript中,我们知道可以使用对象字面量或者构造函数创建对象,但是如何优雅地创建一个对象你却不一定了解。 前人在踩过无数坑又填过无数坑之后,给我们总结了不同场景下的几种对象创建模式: 命名空间模 ...
摘要:转自阮一峰年月日上周,我整理了设计思想之理解篇。这样的设计,使得读取局部变量比读取全局变量快得多。请看下面两段代码,第一段代码是读取全局变量第二段代码是读取局部变量第二段代码读取变量的时候,不用前往上一层作用域,所以要比第一段代码快五六倍。 转自:阮一峰 2011年8月4日 http://www.ruanyifeng.com/blo... 上周,我整理了https://segmentf...
阅读 1815·2021-09-30 09:57
阅读 2115·2021-09-09 09:33
阅读 2615·2021-09-04 16:40
阅读 2173·2021-09-01 10:50
阅读 3501·2021-09-01 10:31
阅读 2806·2019-08-30 15:56
阅读 3140·2019-08-30 15:44
阅读 3632·2019-08-29 17:29