jQuery源码分析系列(一)初识jQuery

一个工厂

(function(global, factory){
   
      "use strict"
      // operation_1
})(typedef window !== "undefined" ? window : this, function (window, noGlobal) {
   
      // operation_2
})

=====>  (function(args,...){
   ...})(params,...)            // 一种自执行方法,形式为(function(){})(),也可以写为 !function(){}() 或 ;function(){}();

其中function(window, noGlobal){}有11000多行代码,并且注入到operation_1中执行。

// operation_1
// 这个一个兼容操作,旨在检测文件是否运行在CommonJS中,如NodeJS,如果是的话进入此分支,一般不会进入
if (typeof module === "object" && typeof module.exports === "object") {
   
	module.exports = global.document ?
		factory(global, true) :		// 如果global.document存在,则向外面暴露出 factory 方法
		function (w) {
   
			if (!w.document) {
   	// 因为不存在w,所以 !w.document为true,所以报错
				throw new Error("jQuery requires a window with a document");
			}
			return factory(w);
		};
} else {
         // 通常直接进入此分支
	factory(global);		// 没有传入noGlobal,将引发其他操作
}

至此完成了方法的注入调用。但是我们发现传入的实参比形参少一个noGlobal,为此我们全局查找此参数

// noGlobal第三次出现在11124行 
if (typeof noGlobal === "undefined") {
               // 如果noGlobal未定义(未传入)
	window.jQuery = window.$ = jQuery;         // 将实例jQuery赋值给窗口的$或jQuery,这也就是$()和jQuery()两个选择器的由来
}

通过使用窗口(全局)的jQuery或$,就可以实现jQuery类或对象的调用,当然调用对象需要用到其构造方法,我们接着往下看

知识点:

  • 自执行方法: 形式有(function(){})()!function(){}();function(){}()
  • “use strict”:开启严格模式,此模式下代码质量要求及书写规范要求更高,但能保证代码的安全,提高编译器效率,加快运行速度
  • typedef module === “object”: 在其他JS模块中的执行检测,详细请跳转至此处

3个变量,6个函数

/**
* 内部变量
*/
var arr = [];
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
...            // 有些变量看起来没有必要定义,但是为了避免魔鬼变量(数字、字符串),代码中具有特殊用途的变量必须定义

/**
* 内部方法
*/
// 数组扁平化,将数组深度遍历并组成新的一维数组
var flat = arr.flat ? function(array){
   
	return arr.flat.call(array);
} : function (array) {
          // 如果不能直接扁平化,则利用concat.apply()方法实现
	// Array.prototype.concat.apply([],array)	递归扫描array数组,并扁平化追加到参数1内,因此需要输入一个空数组
	return arr.concat.apply([], array);
};

// 判断是否是方法
var isFunction = function isFunction(obj) {
    
    return typeof obj === "function" && typeof obj.nodeType !== "number";             // typeof obj.nodeType !== "number",任何DOM元素的nodetype都是数字,常见的有1 9 11
};

// 简单的理解为,创造一个类似node的Script节点(内容为code)并挂载到doc上
function DOMEval(code, node, doc) {
   
    doc = doc || document;

    var i, val, script = doc.createElement("script");

    script.text = code;
    if (node) {
   
        for (i in preservedScriptAttributes) {
    // 对于xx中的每个属性
            // 有些浏览器不支持脚本的“nonce”属性。另一方面,仅仅使用“getAttribute”是不够的,因为每当“nonce”属性连接到上下文时,
            // 它就会重置为空字符串。在`节点.getAttribute`添加支票是为了`jQuery.globalEval`这样它就可以通过一个对象伪造一个包含nonce的节点。
            val = node[i] || node.getAttribute && node.getAttribute(i); // 如果node存在这个属性,则设置到script中
            if (val) {
   
                script.setAttribute(i, val);
            }
        }
    }
    doc.head.appendChild(script).parentNode.removeChild(script); // script挂载到头节点上
}

// 获取对象的类型
function toType(obj) {
   
    if (obj == null) {
   
        return obj + "";	// 强转成字符串,null + "" == "null"
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值