• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
smileyqp
https://github.com/smileyqp
博客园    首页    新随笔    联系   管理    订阅  订阅

(三十四)Jquery源码分析&Jquery中extend方法简单实现

  • 无new化实例对象
  • jquery的简单实现
  • jquery中extend方法的简单实现
(function(window,undefined){
    function jquery(selector){
        return new jquery.fn.init();//返回jquery的函数init构造函数的实例对象
    }
    jquery.fn = jquery.prototype = {
        init : function(){

        },
        css:function(){

        },

    }


    //extend()扩展对象的方法;可以允许给任意对象扩展;包括给jquery本身进行扩展
    /**
     * $.extend({work:function(){}})        jquery.work         jquery的人以对象扩展
     * $.fn.extend({sex:'boy'})             $().sex;    //boy   jquery的实例对象扩展
     * $.fn指的是jquery的原型对象;即jquery的prototype
     * 1、可以给任意对象扩展
     * 2、可以给jquery本身扩展
     * 3、可以给jquery的本身的实例对象扩展
     */
    jquery.fn.extend = jquery.extend = function(){          //给jquery的原型和jquery都加上extend方法
        //按照参数的个数来区分;给任意对象扩展需要传入两个及两个以上对象;给jquery和jquery的实例对象扩展则是只需要传入一个对象(并且第一个参数的类型一定是一个object)
        var target = arguments[0] || {};
        var length = arguments.length;      //获取参数长度
        var i = 1;
        var deep = false;           //用于标识是否做深拷贝;也就是第一个参数的传值是否为布尔值;
        var option,name,copy,src,copyisArray,clone;
        if(typeof target === 'boolean'){
            deep = target;          //是否做深拷贝
            target = arguments[1];      //为了不打乱;将下标为1的参数传给它
            var i = 1;                  //将i的值变成2;方便遍历的时候直接从下表为2的值遍历就可以
        }
        if(typeof target !== 'object'){
            target = {};        //判断传入的第一个参数是否为object;如果不是的话那么就直接创建一个object给它
        }
        //判断当前参数的个数
        if(length === i){       //如果只有一个参数那么就是给jquery扩展或者jquery的实例对象进行扩展
            target = this;          //$.extend({work:function(){}})这种方式调用的话那么this指向的是jquery; $.fn.extend({sex:'boy'}) 这种方式调用的话那么this指向的是jquery的实例对象
            i--;
        }

        //浅拷贝
        for(;i<length;i++){     //此时由于上面设置了i为1;那么extend方法中其实是不用遍历第一个参数对象的知识需要遍历第二个以及第二个之后的对象的
            if((option = arguments[i]) != null){            //将arguments[i]的值赋值给option并且判断一下option是否为null
                for(name in option){        //用name保存option中的key
                    // console.log(name)
                    // target[name] = option.name;
                    copy = option[name];//保存值
                    src = target[name];//如果target中有这个name为key的值的话用src保存;当然第一此遍历的时候由于初始的时候是{}那么src肯定为undefined但是当遍历到有两个相同的key的话那么就不为undefined了
                    console.log(target)
                    if(deep && (jquery.isPlainObject(copy)||(copyisArray = jquery.isArray(copy)))){       //深拷贝;jquery.isPlainObject(copy)判断copy是否为object;并且判断是否为数组,之后 赋值给copyisArray
                        if(copyisArray){
                            copyisArray = false;        //保证下次遍历
                            clone = src && jquery.isArray(src) ? src:[];          //如果copy是一个数组;这里判断src是否是一个数组,如果是的话返回src,繁殖创建一个空数组
                        }else{
                            clone = src && jquery.isPlainObject(src) ? src:{};      //如果是object
                        }
                        target[name] = jquery.extend(deep,clone,copy);
                    }else if(copy !== undefined){
                        target[name] = copy;
                    }
                }
            }
        }
        //在jquery中如果extend函数传入的第一个值是布尔值;那么实际上是要做一个深拷贝的事情
        return target;
    }






    //共享原型对象
    jquery.fn.init.prototype = jquery.fn;



    jquery.extend({
        //类型检测
        isPlainObject:function(){
            return toString.call(obj) == '[object Object]';
        },
        isArray:function(){
            return toString.call(obj) == '[object Array]';
        }
    });




    //工厂模式:建立一个工厂方法;要什么返回什么(适用于快速创建大量对象的情况;大量dom对象)
    window.$ = window.jquery = jquery;//或者windows用root
})(window,undefined);
//js存在作用域链;这里传window是可以减少作用域链的查找;undefined对于js是一个变量,而不是关键字;null对于js而言是一个关键字;null对于js而言没必要像undefined一样去查找

/**
 * JQuery和vue,为什么jquery用工厂方法而vue不用工厂模式
 * - Jquery需要大量创建xianggu8an对象
 * - jquery不同于vue,vue只是给出类,全局只有一个根实例
 * 
 */


 /**
  * jquery
  * - 工厂模式;无new化对象
  */



  /**
   * 整个逻辑梳理:
   * 1、当调用$的时候;实际上是调用function jquery;每一次调用实际上都是new一个jquery;但是由于从其本身去调用本身会出现一个循环;因此就调用jquery的init方法,并且将init的原型对象指向jquery的原型对象这样的话就不会出现循环调用的问题
   */

看源码有时候能看到一些写法以及思想,感觉挺有意思的。继续加油啦沛沛~

posted @ 2019-10-29 17:16  smileyqp  阅读(165)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3