本文介绍jQuery 源码的主体结构和关键细节。

jQuery是前端开发中绕不开的一个框架,在React和Vue等框架出现前,jQuery无疑是前端开发主流技术栈中不可或缺的框架。它为我们提供了强大的DOM操作可靠的事件处理机制简单的动画特效完善的Ajax网络请求好用的工具方法以及超前的链式调用等能力,阅读jQuery框架的源码是必要的。

总体来说,jQuery框架的源码并不复杂,主要几个版本的代码都保持在1W行左右的水准,下面列出jQuery框架最核心的结构。

/* 001-外层是闭包(立即执行函数) */
(function() {
"use strict"; /* 默认开启严格模式 */
let version = "1.0.0"; /* 设置当前框架的版本号 */ /* 002-声明jQuery工厂函数 */
let jQuery = function(selector) { /* 构造函数:jQuery.fn.init */
/* 返回实例:jQuery.fn.init 构造函数创建出来的实例对象 */
return new jQuery.fn.init(selector);
} /* 003-设置jQuery的原型对象 */
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function() {},
eq() {},
get() {},
first() {},
last() {},
toArray() {}
} /* 004-设置原型对象共享(为了让init的实例对象可以访问jQuery原型成员) */
jQuery.fn.init.prototype = jQuery.fn; /* 005-插件方法和插件机制 */
jQuery.fn.extend = jQuery.extend = function(o) {
for (let key in o) {
this[key] = o[key];
}
} jQuery.extend({});
jQuery.fn.extend({}); /* 006-把jQuery和$暴露出去 */
window.jQuery = window.$ = jQuery;
})();

这里再给出jQuery框架中核心入口函数init方法实现的简单版本以及插件机制和核心方法的简单实现。

/* 001-外层是闭包(立即执行函数) */
(function() {
/* 002-默认开启严格模式 */
"use strict"; /* 003-设置当前框架的版本号 */
let version = "1.0.0"; /* 004-声明jQuery工厂函数 */
let jQuery = function(selector) { /* 构造函数:jQuery.fn.init */
/* 返回:jQuery.fn.init构造函数创建出来的实例对象 */
return new jQuery.fn.init(selector);
} /* 005-设置jQuery的原型对象 */
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function(selector) { /* 如果参数为假 */
if (!selector) {
return this;
}
/* 如果参数是函数 */
if ($.isFunction(selector)) {
document.addEventListener("DOMContentLoaded", selector)
}
/* 如果参数是字符串 */
else if ($.isString(selector)) {
/* 标签字符串 "<div>测试</div>" "<a>"*/
if ($.isHTMLSting(selector)) {
let ele = document.createElement("div");
ele.innerHTML = selector;
[].push.apply(this, ele.children)
}
/* 选择器字符串 "div" ".box"*/
else {
[].push.apply(this, document.querySelectorAll(selector));
}
}
/* 如果参数是数组或者是伪数组 */
else if ($.isArray(selector) || $.isLikeArray(selector)) {
//把selector中所有的元素依次添加到this中并且更新length
[].push.apply(this, selector);
} else {
this[0] = selector;
this.length = 1;
} },
eq(index) {
return $(this.get(index));
},
get(index) {
return index >= 0 ? this[index] : this[this.length + index];
},
first() {
return this.eq(0);
},
last() {
return this.eq(-1);
},
toArray() {
return [].slice.call(this);
}
} /* 工具方法的处理 */
/* jQuery插件机制 */
jQuery.fn.extend = jQuery.extend = function(o) {
for (let key in o) {
this[key] = o[key];
}
} jQuery.extend({
isString: function(str) {
return typeof str == "string";
},
isFunction: function(fn) {
return typeof fn == "function";
},
isObject: function(obj) {
return typeof obj == "object" && obj != null;
},
isHTMLSting: function(htmlStr) {
return htmlStr.charAt(0) == "<" && htmlStr.charAt(htmlStr.length - 1) == ">" && htmlStr.length >= 3
},
isArray: function(arr) {
if (Array.isArray) {
return Array.isArray(arr);
} else {
return Object.prototype.toString.call(arr) == "[object Array]";
}
},
isLikeArray: function(likeArr) {
return typeof $.isObject(likeArr) && "length" in likeArr && likeArr.length - 1 in likeArr;
}
}); jQuery.extend({
xxxx() {
console.log("----");
}
}) jQuery.fn.extend({
css: function() {},
text: function() {},
html: function() {}
}); jQuery.fn.extend({
on: function(type, handler) {
// $("button").on("click", function() {
// console.log("click", this);
// })
/* > 给所有选中的标签(this)都添加指定类型的事件,当事件触发的时候要执行事件处理函数 */
for (let i = 0, len = this.length; i < len; i++) {
this[i].addEventListener(type, handler);
}
},
click: function(handler) {
this.on("click", handler);
},
mouseenter: function(handler) {
this.on("mouseenter", handler);
},
mouseleave: function(handler) {
this.on("mouseleave", handler);
}
}); jQuery.fn.extend({
css() {},
attr() {},
addClass() {},
removeClass() {},
toggleClass() {},
append() {}
}) /* 006-设置原型对象共享(为了让init的实例对象可以访问jQuery原型成员) */
jQuery.fn.init.prototype = jQuery.fn; /* 007-把jQuery和$暴露出去 */
window.jQuery = window.$ = jQuery;
})();

前端开发系列073-JQuery篇之源码核心的更多相关文章

  1. leaflet-webpack 入门开发系列六矢量瓦片(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  2. leaflet-webpack 入门开发系列五地图卷帘(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  3. 使用jQuery和CSS3制作数字时钟(jQuery篇) 附源码下载

    HTML 和上一篇文章:使用jQuery和CSS3制作数字时钟(CSS3篇)一样的HTML结构,只是多了个>date用来展示日期和星期的. <div id="clock" ...

  4. pentaho专题系列之kettle篇--kettle源码编译

    最近看了一些kettle的文章,都是kettle7.0以前的,已经跟不上时代了.截止笔者写这篇文章的时候,github上面的已经是7.1.0.3了,而且是发行版的,最新的快照版本已经是8.0的了.基于 ...

  5. openlayers5-webpack 入门开发系列一初探篇(附源码下载)

    前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...

  6. leaflet-webpack 入门开发系列一初探篇(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  7. web前端开发学习:jQuery的原型中的init

    web前端开发学习:jQuery的原型中的init 有大量web前端开发工具及学习资料,可以搜群[ web前端学习部落22群 ]进行下载,遇到学习问题也可以问群内专家以及课程老师哟 jQuery.fn ...

  8. 【Windows10 IoT开发系列】配置篇

    原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry ...

  9. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  10. Jquery.cookie.js 源码和使用方法

    jquery.cookie.js源码和使用方法 jQuery操作cookie的插件,大概的使用方法如下 $.cookie(‘the_cookie’); //读取Cookie值$.cookie(’the ...

随机推荐

  1. java基础之String类、Math类、Arrays类、Collections类

    一.String类 概述:程序中所有的双引号字符串,都是String类的对象.(就算没有new,照样算是) 特点: 1.字符串的内容用不可变[重点] 2.因为字符串[String对象]是不可变的,所以 ...

  2. 多模态自动驾驶混合渲染HRMAD:将NeRF和3DGS进行感知验证和端到端AD测试

    基于3DGS和NeRF的三维重建技术在过去的一年中取得了快速的进步,动态模型也变得越来越普遍,然而这些模型仅限于处理原始轨迹域内的对象. HRMAD作为一种混合方案,将传统的基于网格的动态三维神经重建 ...

  3. kette介绍-Step之Table input

    表输入(Table Input)介绍: Table input用于将数据源的数据加载到Kettle转换中的行集,可以说是数 据从持久化到内存的一种加载变换,故名为输入.加载内部过程,就是通过JDBC ...

  4. 分享5款开源、美观的 WinForm UI 控件库

    前言 今天大姚给大家分享5款开源.美观的 WinForm UI 控件库,助力让我们的 WinForm 应用更好看. WinForm WinForm是一个传统的桌面应用程序框架,它基于 Windows ...

  5. 工具 | ApplicationScanner

    0x00 简介 ApplicationScanner是一款APP客户端安全项检测工具. 下载地址: ApplicationScanner下载: ApplicationScanner下载 0x01 功能 ...

  6. 【笔记】Excel 2021|(二)VBA删除数组中的一个元素、循环时删除一行、选择一列删除指定一行

    主要问题是循环的时候删除一行比较麻烦,因为删除了一行后,循环仍然直接访问后一行,会导致一定的异常. 文章目录 选择一列,删除指定一行 删除数组中的一个元素 方法1:利用动态数组,在循环中条件判断删除 ...

  7. 集合流之"计算集合中的Integer或Double或BigDecimal的sum总和(累计)"

    一.BigDecimal类型 BigDecimal withdrawalFeeExchange = groupDeverList.stream().map(DevWeekReport::getWith ...

  8. 深入理解 JavaScript 模板引擎

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  9. 手把手教你实现MVVM架构

    .markdown-body { color: rgba(89, 89, 89, 1); font-size: 15px; font-family: -apple-system, system-ui, ...

  10. C#之清除已经注册的事件

    private static void DealA(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine($"E ...