无限调用之链模式分析

栏目: JavaScript · 发布时间: 5年前

内容简介:链模式相信大家很常见,尤其在jq中,我们非常习惯的可以使用jq的链式模式中连续的进行方法的调用,虽然我们知道其在方法执行后会返回this的当前对象,来实现这个模式的设计,我们还是进行更加详细的研究学习吧。首先我们知道的是链模式是基于原型,比如我们在假设我们的方法为A。我们现在的方法和属性都是定义在原型链上,a本身是方法,我们通过实例化方法可以访问到原型链上的方法。但是这样是有问题的,我们知道jq的方式是直接用返回对象并没有实例化的方法,那我们可以进行借助另一个对象来实现。

链模式相信大家很常见,尤其在jq中,我们非常习惯的可以使用jq的链式模式中连续的进行方法的调用,虽然我们知道其在方法执行后会返回this的当前对象,来实现这个模式的设计,我们还是进行更加详细的研究学习吧。

基于原型的继承

首先我们知道的是链模式是基于原型,比如我们在假设我们的方法为A。我们现在的方法和属性都是定义在原型链上,a本身是方法,我们通过实例化方法可以访问到原型链上的方法。

function A (){}
A.prototype = {
  length:2,
  size:function(){
    return this.length
  }
}
let a  = new A()
console.log(a.size()) //2

// 没有size 是因为方法定义在原型链上
console.log(A.size())
// 没有size执行是因为a方法的执行没有任何返回值
console.log(A().size())
复制代码

但是这样是有问题的,我们知道jq的方式是直接用返回对象并没有实例化的方法,那我们可以进行借助另一个对象来实现。

借助助手

我们可以借助另外的对象进行,上面讲到A().size()不行是因为a方法没有任何任何值,那么我们可以进行返回。如下的方式改造就可以直接a方法调用函数了。

function A (){
    return B
}
let B = A.prototype = {
  length:2,
  size:function(){
    return this.length
  }
}

console.log(A().size()) //2

// 为了减少变量的创建,我们直接用A的属性来承接
A.fn = A.prototype = {
  length:2,
  size:function(){
    return this.length
  }
}
复制代码

获取元素

我们知道jq最终是为了获取元素的集合,所以目前的方式肯定是不合适的。所以我们需要在原型对象上定义一个init方法来获取对象。那么我们需要在A方法执行的时候直接返回我们的初始化方法。

function A (seletor){
    return A.fn.init(seletor)
}

A.fn = A.prototype = {
 init:function(seletor){
    return document.getElementById(seletor)
 },
 length:2,
 size:function(){
  return this.length
 }
}
console.log(A("demo")) // dom 
复制代码

返回我们需要的方法

虽然之前的设计可以得到元素了,但这样的元素不具有我们想要的方法,那么如何让返回的元素具有我们想要的方法呢,在方法体重我们可以看到A.fn是具有我们的方法的。

function A (seletor){
    return A.fn.init(seletor)
}

A.fn = A.prototype = {
 init:function(seletor){
    this[0] = document.getElementById(seletor)
    this.length = 1 
    return this
 },
 length:2,
 size:function(){
  return this.length
 }
}
console.log(A("demo").size()) // 1 得到校验后的长度
复制代码

此时发现另外的问题了,就是我们进行另外一个元素的使用时,元素会互相覆盖,原因是因为我们每次都是返回利用的同一个对象。

覆盖获取

解决覆盖获取的方式也很简单,恢复实例化即可。但这样也会导致方法无法使用。报错如下: A(...).size is not a function

function A (seletor){
    return new A.fn.init(seletor)
}
复制代码

方法丢失

原因是因为前者返回的是当前对象,也就是A.fn和A.prototype,但如果是new的进行的是属性的复制,与前面不同。

经过测试,init方法中第一种方式返回的确实是a.fn,a.prototype,而如果是返回new a.fn.init,那么返回的是a.fn.a.init

jq的解决方案

直接将a.fn的原型指向存在的对象即可。

A.fn.init.prototype = A.fn
复制代码

这样就可以满足我们的基本需求了。

丰富的元素获取

上面的代码可以实现获取id元素的标签,但实际上我们有各种可能,这种时候只要判断选择器的内容,然后针对性的获取元素就好。

init:function(selector,context){
    this.length = 0
    context = context || document
    if(~selector.indexOf("#")>-1){
     this[0] =                                      document.getElementById(selector.slice(1))
     this.length = 1
    }
    ...
}
复制代码

数组与对象

虽然我们实现了基本的方法,但发现仍然存在一个使用上的特性,就是jq的元素支持数组的很多操作,为了让我们的返回对象也具有类似的功能,我们需要在原型链上追加push\sort\split等类似数组的方法来实现。

A.fn = A.prototype = {
 // 数组方法添加 增强数组特性
 push:[].push,
 sort:[].sort,
 splice:[].splice

}
复制代码

方法拓展extend

A.extend = A.fn.extend = function(){
    var i = 1,len = arguments.length,
    target = arguments[0]
    if(i === len){
    target = this ;
    i--
    }
    for(;i<len; i++){
     for(j in arguments[i]){
      target[j] = arguments[i][j]
     } 
    }
    return target ;
    
}
复制代码

添加方法,返回this

所以如果你要添加方法,你直接用就可以。

A.fn.extend = ({
 html:function(){
    var arg = arguments,len = arguments.length;
    if(len === 0){
    return this[0] && this[0].innerHtml;
    } else {
     for(var i = this.length -1 ; i >=0 ; i-- ){
        this[i].innerHtml = arg[0]
     }
    }
    // 返回this 支持链式调用
    return this
 }
})
复制代码

以上所述就是小编给大家介绍的《无限调用之链模式分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Computers and Intractability

Computers and Intractability

M R Garey、D S Johnson / W. H. Freeman / 1979-4-26 / GBP 53.99

This book's introduction features a humorous story of a man with a line of people behind him, who explains to his boss, "I can't find an efficient algorithm, but neither can all these famous people." ......一起来看看 《Computers and Intractability》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具