JQuery设计模式之源码分析(三)

3.1jQuery中$.Callbacks的函数对象的实现

$.Callbacks作用: $.Callbacks用于管理函数队列。

$.Callbacks的使用: 我们通过调用$.Callbacks(options)获取到一个Callbacks实例

内部API分别有:

  1. add => 向内部队列添加函数
  2. fire依次执行队列里的函数

构造参数分别有:

  1. “stopOnFalse” => 内部队列里的函数是依次执行的,当某个函数的返回值是false时停止继续执行剩下的函数
  2. “memory” => 当函数队列fire一次后内部会记录当前fire的参数。当下次调用add的时候,会把记录的参数传递给新添加的函数并立即执行这个新添加的函数。

 (function(root){
 	// 用于缓存构造传入的参数值
    var optionsCache = {}
    var _ = {
    	// 定义Callbacks
        callbacks: function(options){
            options = typeof options === "string" ? (optionsCache[options] || createOptions(options)) : {};
            var list = [] // 队列添加处理函数
            var index,length,testTing,memory,start,starts
            var fire = function(data){// 执行队列里的处理函数
                memory = options.memory && data 
                index = starts || 0
                start = 0
                testTing = true
                length = list.length
                for(;index < length;index++) {
                    if(list[index].apply(data[0],data[1]) === false && options.stopOnfalse){
                        break; // 终止后面的处理函数的执行
                    }
                }
            }
            var self = {
            	// 向内部队列添加函数
                add: function(){
                    var args = Array.prototype.slice.call(arguments)
                    start = list.length
                    args.forEach(function(fn){
                        // 使用toString.call用于检索数据类型
                        if(toString.call(fn) === "[object Function]") {
                            if(!options.unique || !self.has(fn,list))list.push(fn) // 处理函数的唯一性
                        }
                    })
                    if(memory){
                        starts = start
                        fire(memory) // 如果memory为undefined则不执行fire
                    }
                    return this
                },
                // 上下文的绑定
                fireWith: function(context,arguments){ 
                    var args = [context,arguments] 
                    if(!options.once || !testTing){
                        fire(args) //调用外面的fire方法
                    }
                },
                // 依次执行队列里的函数
                fire: function(){
                    self.fireWith(this,arguments)
                },  
                // inArray作为一个接口对外使用
                has: function(fn,array){
                    return self.inArray(fn,array) > -1 
                },
                // 判断数组中是否存在某元素
                inArray: function(elem,arr){
                    return arr === null ? -1 : [].indexOf.call(arr,elem)
                }
            }
            return self
        }
    }
    // 创建参数
    function createOptions(options){
    	// 按参数值设置为缓存对象中的属性对象,初始为{}
        var object = optionsCache[options] = {}
        // 可按空格分割字符串成数组时遍历分割字符串
        options.split(/\s+/).forEach(value => {
            object[value] = true // 按分割字符串值作为当前创建对象的属性,初始为true
        });
        return object // 返回当前创建的参数对象
    }
    root.$ = _; 
 })(this) // this指向当前window对象

3.2Function.call和Function.apply以及Function.bind的使用区别

代码举例理解如下:

		<script>
			/**
			 * 如果当作类使用时,this指向当前实例对象
			 * 如果当作构造函数使用时,this指向window    
			 * 如果作函数使用时fn是Function实例对象存在
			 */
            function fn(){ 
                this.name = "max" 
                console.log("当前this指向=>",this) 
            }
            new fn() // 当作类使用,this指向当前实例对象
            fn() // 当作函数使用,this指向当前window对象
            console.log(fn.apply(Object)) // 调用当前fn函数,改变它内部this的指向

            /**
             * 模拟slice.call调用方式
            */
            Array.prototype.mySlice = function(start,end){
                var result = new Array()
                start = start || 0
                end = end || this.length    
                for(var i = start;i < end;i++){
                    result.push(this[i])
                }
                return result
            }
            function Fn(a,b,c,d){
                console.log("arguments=>",arguments)
                return [].mySlice.call(arguments) // 调用当前原型函数mySlice,改变它内部this的指向
            }
            console.log(Fn(1,2,3,4))
            /**
             * Function原型方法call和apply的使用区别
            */
           function FN(a,b,c,d){
                console.log("this指向=>",this)
                console.log("a,b,c,d=>",a,b,c,d)
           }
           var obj = {}
           FN.call(obj,1,2,3,4) // 打印结果为:this指向=> Object    a,b,c,d=> 1 2 3 4
           FN.apply(obj,[1,2,3,4]) // 打印结果为:this指向=> Object    a,b,c,d=> 1 2 3 4
           /**
            * Function原型方法bind的使用
           */
          var FNBind = FN.bind(obj,5,4) // 创建FN的副本
          console.log(FNBind(3,2)) // 打印结果为:this指向=> Object    a,b,c,d=> 1 2 3 4
    </script>

待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值