likes
comments
collection
share

jQuery源码解析

作者站长头像
站长
· 阅读数 40

知识点

JS代码可以运行的环境(平台)

  • 浏览器「webview」:存在window全局对象、但是不支持CommonJS模块规范【模块的导入导出】

  • node环境 : 没有window(它的全局对象是Global)、支持CommonJS模块规范【模块的导入导出】

    • cmd $node 开启Node的repl命令
    • module.exports 模块导出
  • webpack环境 : 基于node把资源文件合并打包,最后交给浏览器来运行,所以 它里面既有window全局对象,也支持CommonJS模块规范

webview:App中一个非常重要的控件,它的作用是用来展示一个web页面。它使用的内核是webkit引擎,

jQuery源码解析

数组的扁平化

  • Array.prototype.flatES6新增的一个数组方法,它的作用就是用来数组扁平化,并且根据传入的参数来决定展开的层级,是数组扁平化的终极解决方案

  • 本文中的数组的扁平化就是用的这个方法,如果数组没有flat方法就给它加一个

工厂设计模式

“new 构造函数”是可以创建类的实例的,但是我们如何做到,不使用new,只把构造函数当做普通函数执行,也能创造这个类的一个实例呢?==>工厂设计模式

jQuery源码解析

图解

jQuery源码解析

思路

  • 如果window存在,则global=window;如果不存在global=this;
  • factory方法才是JQ的核心,之前的闭包只是为了做一个环境区分
    • 浏览器「webview」:window=window noGlobal=undefined
    • WEBPACK:window=window noGlobal=true => module.exports = factory执行的结果;
    • JQ不支持在NODE环境下运行(因为里面不具备window全局对象)
    • 在某个函数的第一行写"use strict" 当前函数运行就按照严格模式运行
  • 数组的扁平化
    • 如果数组没有flat方法就给它加一个
  • 暴露API
  • 如果是在浏览器中运行JQ,我们直接在window上挂载jQuery/$属性,属性值是jQuery这个方法
    • $() 或者 jQuery() :就是把jQuery这个方法执行
    • 在webpack环境中运行,则module.exports=jQuery;(使用let $=require('jquery'))

代码实现

var global = typeof window !== "undefined" ? window : this;

var factory = function (window, noGlobal) {
   
    "use strict"; //开启严格模式

    var arr = [];

    var getProto = Object.getPrototypeOf; //原型对象

    //数组的扁平化  
    var flat = arr.flat ? function( array ) {
        return arr.flat.call( array );
    } : function( array ) {
        return arr.concat.apply( [], array );
    };


    var version = "3.6.0",
        jQuery = function (selector, context) {
            //context 上下文 限定它获取的范围
            return new jQuery.fn.init(selector, context);
        };
    jQuery.fn = jQuery.prototype = {
        // jQuery是一个构造函数,原型上提供的方法是供其实例使用的
    };

   //另一种方式
   //当做类、类的原型【公共的属性方法 供实例调用】
   //jQuery.fn是给他设置的小名
   //jQuery.prototype重定向到新的对象 需要保证constructor
   var init = jQuery.fn.init = function (selector, context, root) {
        // ...
    };
    
    init.prototype = jQuery.fn;
   
    if (typeof noGlobal === "undefined") {
        window.jQuery = window.$ = jQuery;
    }
    return jQuery;
};  

闭包写法

思路

  • 如果当前JQ是运行在浏览器或者webpack环境下,则global=window;如果运行在node环境下,则global=Global;支持CommonJS规范的是webpack和node环境;

  • 支持CommonJS规范:webpack、node

  • 只有window才会有document的属性

  • 不支持CommonJS规范:浏览器、webview

代码实现

(function (global, factory) {
    "use strict";
    if (typeof module === "object" && typeof module.exports === "object") {       
        module.exports = global.document ?
            factory(global, true) :
            function (w) {
                if (!w.document) {
                    throw new Error("jQuery requires a window with a document");
                }
                return factory(w);
            };
    } else {
        factory(global);
    }
})(global, factory); 
转载自:https://juejin.cn/post/7176195328897450045
评论
请登录