zoukankan      html  css  js  c++  java
  • jquery源码部分分析

    1.整体架构和如何辨别浏览器端和node端

    自执行函数,判断在什么端,如果在浏览器端就执行factory函数

    //(function(){a,b})(a,b)
    //jq大架构,闭包,自执行函数,传入函数参数(factory:工厂模式)
    (function(global,factory){
      "use strict" //严格模式
      if(typeof module ==="object" && typeof module.exports ==="object"){
        //说明支持CommonJS模块规范的(例如Node)
        //...
      }else{
        //浏览器端
        // factory(window) => 就是传入的函数参数执行 => function( window, noGlobal){
        //    window === window    noGlobal === undefined(因为执行这个函数的时候,没有传第二个参数)  
        //}
        factory(global);
      }
    })(typeof window !== "undefined" ? window : this ,function( window, noGlobal){
    
    })
    
    /*
    参数一:
    typeof window !== "undefined" ? window : this
      区分在浏览器端运行还是Node端运行
      typeof xx 如果xx不存在,不会报错,而是返回undefined(js中的暂时性死区问题)
      typeof window !== "undefined" 这个成立,则他在浏览器端或者webView端(浏览器端存在window),不存在说明是Node端运行,this代指当前Node模块
      =>第一个参数就是让global知道是在什么端运行的
    
    参数二:factory为一个函数
    function( window, noGlobal){}
    
    */
    

    2.factory函数

    factory为自执行函数传入的参数,并且在判断为浏览器端后执行,并且传入window对象 factory(global)

    (function(global,factory){
        factory(global);
    })
    (typeof window !== "undefined" ? window : this ,function( window, noGlobal){
        // $() jQ选择器
        //因为window.jQuery = window.$ = jQuery,所以我们$()执行的就是这个函数
        
        var jQuery = function(selector,context){
            return new jQuery.fn.init(selector,context)
        }
        //---------------------------each
        jQuery.fn.each =function (callback){
          //jQuery.each(jQ实例,callback)
           return jQuery.each(this.callback);
        };
        jQuery.each = function(obj,callback){
            //obj可以是数组(类数组) 或者 对象 =>用来遍历它们
        }
        //-------------------------extend向jq和jq原型上扩展方法
        //=>向原型扩展方法是给jq实例用的,一般应用于jq插件封装
        //=>向jq对象中扩展的方法是为了完善类库
        //$.fn.extend({})  $.fn.extend(true,{})
        jQuery.extend = jQuery.fn.extend = function(){
            
        }
        
        //--------------------------jQuery是一个类,它的原型上放了好多属性和方法
        jQuery.fn = jQuery.prototype = {
            //保证原型对象上的构造函数完整性
            constructor : jQuery,
            //...
        };
        //init 也是一个类 
        //new jQuery.fn.init(selector,context) => $()选择器是创建这个类的一个实例,所以$()就可以调用init原型上的方法
        //实例本应该指向init.prototype,但是我们让init.prototype =jQuery.prototype,所以最终类的init实例的__proto__指向的是jQuery.prototype,也就是类似于创建了一个jQ类的实例 => $()jQ选择器就是jQ类的一个实例,此实例可以调取JQ原型上的方法
        var init = jQuery.fn.init=function(selector,context){
            //....
        }
        init.prototype = jQuery.fn = jQuery.prototype;
        
        //冲突处理的( noConflict无冲突) =>$.noConflict()
        //一个项目中引入了多个类库,其中一个类库(例如:zepto)用的也是$=>$===Zepto,此时如果也导入了JQ,那么$到底代表谁就冲突了
        //假设zepto先引入,jq后引入,我们就把$的使用权给zepto,然后函数中又return了jquery
        //所以,如果有冲突的时候,我们可以 let j = $.noConflict(); 以后 j 就代替了$
        var _jQuery = window.jQuery,
            _$ = window.$;
        jQuery.noConflict = function(deep){
            if(window.$ === jQuery){
                window.$ = _$;
            }
            if(deep && window.jQuery ===jQuery){
                window.jQuery = _jQuery
            }
            return jQuery
        }
        
    	//这里为factory的函数体
        //如果是浏览器端运行,条件成立  !undefined
        if(!nonoGlobal){
            //把jQuery或者$暴露到全局对象中(这样当外部引用了jquery的时候,就可以直接调用里面定义的方法)
            window.jQuery = window.$ = jQuery
        }
    })
    
    //=>jQ选择器其实就是把jQuery方法执行
    //$() =>function(selector,context){} 让他执行
    //$('.box')获取当前页面中样式类为box的盒子(范围/上下文:整个页面)
    //$('.banner .box')获取.banner的盒子后代为.box的盒子  =>     等价于$('.box',document.getElementById('banner'))
    

    选择器

    $([selector])
    [selector]支持三种类型
    	"string" => 基于css选择器获取元素 (底层都是使用正则来一点一点匹配的)
     	元素节点  => 把DOM元素转换为jQ对象 (jQ类的实例)
        函数     =>  $(document).ready(函数) 
    
    1.传css选择器为常见用法
    2.传节点,常用于将dom对象转换为jq对象,方便调用jq内置方法
    	let boxList = document.querySelectorAll('.box')
        let $boxList = $(boxList)  //转换为jq对象
        let box1 = $boxList[0] //将jq对象转换为原生dom,jq对象
    3.传函数常用于开头,代码都再传入的函数中编写
    $(function(){
        //等价于 $(document).ready(函数)  当整个页面的DOM结构加载完成
    })
    

    分析源码后的一些应用问题

    //$('.box')每一次执行都是创建一个JQ的新实例(jQ对象)
    // => $('.box') !== $('.box') 两个不同的实例,开辟了两个堆内存
    let $box = $('.box');
    $('.box').click(()=>{}) 
    $('.box').addClass()
    $('.box').fadeIn()
    //这样虽然能实现效果但是,开辟了三个堆内存,消耗性能,所以我们应该尽量用一个变量来接收,用这个变量区操作属性
    $box.click(()=>{}) 
    $box.addClass()
    $box.fadeIn()
    
    //在控制台输出jQuery.fn可以查看原型上的方法,这些方法都可以被实例所调用(此时把jq看作一个类)
    //获取一个实例,再使用dir查看
    let $box = $('.box')
    console.dir($box)
    //但jq也是一个普通对象,再普通对象上也有很多方法,这些方法和实例没有直接的关系,基于$.xxx()调用,例如:$.Callbacks() 或者 $.ajax() 等 
    console.dir(jQuery)
                
    
    ---------------------------------------------------------
     //向jquery原型中拓展方法
                $.fn.extend({
                	aaa(){  console.log('a') }
                })
    ------------------------------------------------------------
     //each (当返回值为false的时候,结束循环,forEach不支持)
     //  =>   $.each($('.box'),function(){})
     // 等价于$('.box').each(function(){})
    $.each([10,20,30],function(item,index)=>{})  //不能用箭头函数,没有this
    $.each({age:10,name:小黄},function(key,value){
        //参数顺序和数组的forEach是相反的
        //this => value
    })
    
  • 相关阅读:
    OAuth2.0介绍
    C#集成FastDFS断点续传
    ABP集成WIF实现单点登录
    CentOS7下搭建FastDfs(V5.11)+Keepalived分布式集群部署
    【算法】之常见的排序算法
    【开发工具
    【C/C++】之C/C++快速入门
    【数据结构】之二叉树(Java语言描述)
    【数据结构】之散列链表(Java语言描述)
    【数据结构】之队列(Java语言描述)
  • 原文地址:https://www.cnblogs.com/JCDXH/p/12315521.html
Copyright © 2011-2022 走看看