1.实现jQuery构造函数和extend

实现jQuery构造函数

现在我们想实现$()这种形式的函数调用并返回一个对象.

(function(global){

  var $,jQuery;

  $ = jQuery = function(){
      return new jQuery.fn.init();
  }

  jQuery.fn = jQuery.prototype = {
      init:function(){
        
      }
  }

  jQuery.fn.init.prototype = jQuery.fn;


  global.$ = global.jQuery = $;

}
)(window)

解析:我们把$定义为一个函数,但是怎么调用函数可以返回一个对象呢?可以想办法在函数内new一个构造函数返回.因此在jQuery的原型上创建一个init方法就将它作为jQuery的构造函数.另外还要将jQuery的原型赋值给init函数的原型.这样做的好处便是我们在jQuery.prototype上创建的各种方法是可以被new出来的jQuery实例调用的.

 

 

实现$.extend

(function(global){

  var $,jQuery;

  $ = jQuery = function(){
      return new jQuery.fn.init();
  }

  jQuery.fn = jQuery.prototype = {
      init:function(){
        
      },
      isPlainObject:function(data){
        return Object.prototype.toString.call(data) === "[object Object]";
      },
      isArray:function(data){
        return Object.prototype.toString.call(data) === "[object Array]";        
      },
      isBoolean:function(data){
          return typeof data === "boolean";
      }
  }

  jQuery.extend = jQuery.prototype.extend = function(){

    var target = arguments[0] || {};

    var i = 1,isDeep = false,isArrayData = false;

    if(typeof arguments[0] === "boolean"){ //第一个参数是boolean型
        isDeep = arguments[0]?true:false;
        target = arguments[1] || {};
        i = 2;
    }

    var arr = Array.prototype.slice.call(arguments,i);

    if(arguments.length == 1){
        target = this;
        arr = [arguments[0]];
    }

    arr.forEach((obj)=>{
            for(let key in obj){

                if(isDeep){ //深拷贝
                    let src = obj[key];
                    let des = target[key];
                    let copy;
                    if(jQuery.isPlainObject(src) || (isArrayData = jQuery.isArray(src))){
                        //src是数组或者对象类型    
                        if(isArrayData){
                            copy = jQuery.isArray(des)?des:[]
                        }else{
                            copy = jQuery.isPlainObject(des)?des:{};
                        }

                        target[key] = jQuery.fn.extend(isDeep,copy,src); //这一句代码是精髓之处

                    }else{
                        target[key] = obj[key];               
                    }

                    isArrayData = false;

                }else{
                  target[key] = obj[key];                    
                }

            }      
    })

    return target;

  }

  jQuery.fn.init.prototype = jQuery.fn;

  jQuery.extend(jQuery.fn);


  global.$ = global.jQuery = $;

}
)(window)

结果验证

console.log($.extend(true,{a:1,b:2,c:[1,2],e:{k:12}},{d:18,c:[3],e:{m:28,c:[1,2,34],f:{k:12}}}));

                                                            

解析:$.extend实现的难点在深拷贝的处理上,当遍历源数据获取对象上的属性值时需要先判端这个值是不是对象或者数组,如果是其中之一外加上有深拷贝的标识就要开始做深拷贝的处理.我们通过判端des的类型和src的类型来确定copy的值.如果src源数据是数组,那么就要判端des是什么类型了,如果它也是数组,就要合并两个数组,把des赋值给copy.如果它不是数组,就把copy设置为空数组也能实现合并.src源数据是对象的话判端原理也如此,最后通过一句target[key] = jQuery.fn.extend(isDeep,copy,src)点睛之笔就实现了数组类型或者对象类型的合并.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值