jquery 链模式调用简易实现

   <script>// 定义一个名为A的构造函数,接受selector和context参数var A = function (selector, context) {// 返回一个新的A.fn.init实例return new A.fn.init(selector, context);}// 设置A的原型和fn属性A.fn = A.prototype = { // 强化构造器:// 当显式地重写 A.prototype(如通过 A.fn = A.prototype = {...} 赋值时),// 默认情况下 A.prototype.constructor 会丢失,变为指向 Object.// 因此,需要手动将 constructor 重新指向 A,以保持逻辑的正确性。constructor: A,// 初始化方法,接受selector和context参数init: function (selector, context) {// 初始化length属性为0this.length = 0;// 设置默认上下文为documentcontext = context || document;// 根据selector的不同情况,执行不同的DOM查询if (~selector.indexOf('#')) {// 如果是ID选择器this[0] = context.getElementById(selector.slice(1));this.length = 1} else if (~selector.indexOf('.')) {// 如果是类选择器const elements = document.getElementsByClassName(selector.slice(1));for (let i = 0; i < elements.length; i++) {this[i] = elements[i];}this.length = elements.length;} else {// 如果是标签选择器const elements = context.getElementsByTagName(selector);for (let i = 0; i < elements.length; i++) {this[i] = elements[i];}this.length = elements.length;}// 设置selector和context属性this.selector = selector;this.context = context;// 返回当前实例return this;},// 返回实例的长度size: function () {return this.length;},// 初始化length属性length: 0,// 增强数组。push: [].push,splice: [].splice,sort: [].sort}// 设置A.fn.init的原型为A.fn// 在 JavaScript 中,构造函数的实例会继承构造函数的原型 (prototype),// 这使得实例可以访问构造函数原型上的方法。// A.fn = A.prototype = { ... } 设置了 A 构造函数的原型为 A.fn,// 使得 A 的实例可以访问 A.fn 中定义的方法(如 init 方法、size 方法等)。// 但 init 是作为 A.fn.init 构造函数的 prototype 属性来定义的,而不是直接在 A.fn 上定义的。// 所以,A.fn.init.prototype = A.fn; 是为了确保通过 new A.fn.init() 创建的实例能够继承 A.fn 中的所有方法。A.fn.init.prototype = A.fn;// 扩展方法,用于扩展A或A.fn// 对 A 的方法扩展是 静态方法,直接用A.XXX() 调用。// 对 A.fn 的方法扩展是 实例方法。用 obj = new A(); obj.xxx() 实例对象调用。A.extend = A.fn.extend = function () {var i = 1, len = arguments.length, target = arguments[0], j;// 如果只有一个参数,则将target设为thisif (i == len) {target = this;i--;}// 遍历参数对象,将属性复制到targetfor (; i < len; i++) {for (j in arguments[i]) {target[j] = arguments[i][j];}}// 返回扩展后的对象return target;}// 添加事件监听方法A.fn.extend({on: (function () {// 根据浏览器支持情况,选择事件监听方法if (document.addEventListener) {return function (type, fn) {var i = this.length - 1;for (; i >= 0; i--) {this[i].addEventListener(type, fn, false);}return this;}} else if (document.attachEvent) {return function (type, fn) {var i = this.length - 1;for (; i >= 0; i--) {this[i].attachEvent('on' + type, fn);}return this;}} else {return function (type, fn) {var i = this.length - 1;for (; i >= 0; i--) {this[i]['on' + type] = fn;}return this;}}})()})// 驼峰命名方法,用于将CSS属性名转换为驼峰命名A.extend({camelCase: function (str) {return str.replace(/-(\w)/g, function (all, letter) {return letter.toUpperCase();})}})// CSS方法,用于设置或获取CSS属性A.fn.extend({css: function () {var args = arguments, len = args.length;// 根据参数数量和类型,执行不同的逻辑if (this.length < 1) {return this;}if (len === 1) {if (typeof args[0] === 'string') {if (this[0].currentStyle) {return this[0].currentStyle[A.camelCase(args[0])];} else {return getComputedStyle(this[0], false)[A.camelCase(args[0])];}} else if (typeof args[0] === 'object') {for (var i in args[0]) {for (var j = this.length - 1; j >= 0; j--) {this[j].style[A.camelCase(i)] = args[0][i];}}}} else if (len === 2) {for (var j = this.length - 1; j >= 0; j--) {this[j].style[A.camelCase(args[0])] = args[1];}}return this;}})// attr方法,用于设置或获取DOM元素的属性A.fn.extend({attr: function (name, value) {var arg = arguments, len = arg.length;if (this.length < 1) {return this;}if (len === 1) {if (typeof arg[0] === 'string') {return this[0].getAttribute(arg[0]);} else if (typeof arg[0] === 'object') {for (var i in arg[0]) {for (var j = this.length - 1; j >= 0; j--) {this[j].setAttribute(i, arg[0][i]);}}}} else if (len === 2) {for (var j = this.length - 1; j >= 0; j--) {this[j].setAttribute(arg[0], arg[1]);}}return this;}})// html方法,用于设置或获取DOM元素的HTML内容A.fn.extend({html: function (html) {var arg = arguments, len = arg.length;if (len === 0) {return this[0] && this[0].innerHTML;} else {for (var j = this.length - 1; j >= 0; j--) {this[j].innerHTML = arg[0];}}return this;}})
</script>

问题:为什么在 A 的构造函数中要返回 A.fn.init(selector, context) 的实例?

A 是一个构造函数,而 A.fn.init 是实际的构造函数,用来执行选择器的初始化和 DOM 操作。A 的构造函数中返回 new A.fn.init() 的实例,主要目的是为了创建一个可以处理 DOM 元素的对象实例,并确保可以使用类似 jQuery 的链式调用方式。下面详细分析为什么要这么做:

1. 为了支持链式调用

  • 在现代 JavaScript 库(如 jQuery)中,通常会支持链式调用,允许开发者对同一个对象连续调用多个方法。
  • A.fn.init 实际上是构造函数,它执行 DOM 查询并返回一个具有相关功能的对象。通过 new A.fn.init() 创建的实例会附带一个方法集合(比如 .size().push() 等),可以继续在同一个实例上调用其他方法。
  • 比如,你可以写如下代码:
    var obj = new A('#id').size().push('item');
    这个链式调用依赖于 A.fn.init 的构造函数返回的对象保持对实例的引用,允许连续调用 A.fn.initA.fn 上定义的其他方法。

2. AA.fn.init 的关系

  • A 是外部可用的构造函数,用来初始化和返回一个处理 DOM 元素的对象实例。
  • A.fn 是一个空对象,表示 A 构造函数的原型,存放 A.fn.init 等实例方法。
  • A.fn.init 是实际负责 DOM 查询和实例化的构造函数。new A.fn.init() 用来执行选择器逻辑,并返回一个包含 DOM 元素的实例对象。

3. 避免重复代码

  • A.fn.init 被设计成执行所有与 DOM 查询和元素操作相关的逻辑。通过返回 new A.fn.init(selector, context),我们避免了在 A 构造函数中重复编写查询和初始化代码。A 仅仅作为外部接口,将具体的查询逻辑委托给 A.fn.init 来处理。

4. 保持对象的正确性

  • 在构造函数 A 内部使用 new A.fn.init(selector, context) 是为了确保返回的对象是 A.fn.init 的实例,并且它具有正确的原型链。
  • A.fn.init.prototype = A.fn; 这行代码确保了 A.fn.init 的实例(即 new A.fn.init() 创建的对象)能够访问 A.fn 中的方法。这样,无论是通过 new A() 还是 new A.fn.init() 创建的对象,都能够继承 A.fn 上的方法,保持一致的行为。

5. 处理 selectorcontext 参数

  • A.fn.init 的构造函数负责根据选择器和上下文来初始化 DOM 查询。它会根据选择器字符串(如 #id.classdiv)来选择 DOM 元素,并将其存储在实例对象的 length 属性及索引属性中。
  • 返回 new A.fn.init(selector, context) 的实例能够确保 selectorcontext 正确传递并处理,且每次实例化都能返回一个新对象。

总结:

返回 new A.fn.init() 的实例有几个核心目的:

  • 支持链式调用:通过返回一个包含相关方法的对象实例,允许开发者对返回的对象进行连续操作。
  • 分离关注点A 构造函数负责创建实例并返回,而实际的初始化逻辑(如 DOM 查询)则委托给 A.fn.init
  • 保持原型链一致性:通过正确的原型设置,确保返回的实例能够继承并访问到定义在 A.fn 上的方法。
  • 复用逻辑:避免代码重复,通过 new A.fn.init() 委托给 A.fn.init 进行处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/20247.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

无人机侦察打击方案(1)

​​​​​ 概述 任务来源于无人机侦察研制任务&#xff0c;涵盖无人机目标昼夜识别与跟踪、目标定位等功能任务。 组成及功能 无人机侦察系统设备构成如下图所示&#xff0c;分为光电云台、激光打击设备与操控端构成。 图 1 设备组成与链路 光电云台完成无人机目标自主识别…

Windows 系统通过 MSTSC 上传文件到 Windows 云服务器

操作场景 文件上传 Windows 云服务器的常用方法是使用 MSTSC 远程桌面连接&#xff08;Microsoft Terminal Services Client&#xff09;。本文档指导您使用本地 Windows 计算机通过远程桌面连接&#xff0c;将文件上传至 Windows 云服务器。 前提条件 请确保 Windows 云服务…

激光雷达定位初始化的另外一个方案 通过键盘按键移动当前位姿 (附python代码)

通常使用的是通过在 rviz 中点选指定初始化位置和方向来完成点云的初始化匹配。 但是这种粗略的初始化方法有时候可能不成功,因此需要使用准确的初始化方法,以更好的初始值进行无损检测配准。 为了提供更好的匹配初始值,我使用 Python 脚本获取键盘输入,并不断调整这个匹配…

枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~

目录 认识枚举 全文重点&#xff1a;枚举在单例模式中为什么是安全的&#xff1f; Lambda 表达式 概念&#xff1a; 函数式接口 lambda表达式的基本使用&#xff1a; lambda表达式的语法精简&#xff1a; lambda表达式的变量捕获 Lambda在集合当中的使用 在 Collecti…

【JAVA】一次操蛋的nginx镜像之旅

一、前言 由于我们的项目中使用到了nginx&#xff0c;同时我们的nginx是通过docker镜像进行安装的&#xff0c;由于nginx出现了问题&#xff0c;需要重新安装。于是。。。 二、通过docker进行安装 docker pull nginx:latest 1.5.2 脚本文件 在/home/docker/script路径下创…

高并发场景下的热点key问题探析与应对策略

目录 一、问题描述 二、发现机制 三、解决策略分析 &#xff08;一&#xff09;解决策略一&#xff1a;多级缓存策略 客户端本地缓存 代理节点本地缓存 &#xff08;二&#xff09;解决策略二&#xff1a;多副本策略 &#xff08;三&#xff09;解决策略三&#xff1a;热点…

.NET 9 的新增功能

文章目录 前言一、.NET 运行时二、序列化三、缩进选项四、默认 Web 选项五、LINQ六、集合七、PriorityQueue.Remove() 方法八、密码九、CryptographicOperations.HashData() 方法十、KMAC 算法十一、反射十二、性能十三、循环优化十四、本机 AOT 的内联改进十五、PGO 改进&…

11.19.2024刷华为OD

文章目录 HJ51HJ53 杨辉三角HJ56HJ57 高精度整数加法HJ58HJ60 简单题HJ63 DNA序列&#xff08;简单题&#xff09;语法知识记录 HJ51 https://www.nowcoder.com/practice/54404a78aec1435a81150f15f899417d?tpId37&tags&title&difficulty0&judgeStatus0&…

小米表盘自定义工具支持最新小米9pro

app下载(v5.2.28) 点击下载 介绍 米坛小米表盘自定义工具是专为小米手环用户设计的软件&#xff0c;它具备以下特点和功能&#xff1a; 兼容性广泛&#xff1a;支持包括小米手环7、7Pro、8、8Pro、9、9Pro以及小米手表S3、S4在内的多款设备。 持续更新&#xff1a;软件不断…

算法-二叉树(从理论知识到力扣题,递归、迭代。)

二叉树 一、二叉树理论知识1、种类a.满二叉树b.完全二叉树c.二叉搜索树d.平衡二叉搜索树 2、java对于树的理解3、存储a.链式存储&#xff08;常用&#xff09;b.数组存储 4、遍历方式a.深度优先搜索b.广度优先搜索 5、树的定义&#xff08;链式&#xff09; 二、力扣题解写题思…

青训营刷题笔记10

问题描述 小C拿到了一个排列&#xff0c;她想知道在这个排列中&#xff0c;元素 xx 和 yy 是否是相邻的。排列是一个长度为 nn 的数组&#xff0c;其中每个数字从 11 到 nn 恰好出现一次。 你的任务是判断在给定的排列中&#xff0c;xx 和 yy 是否是相邻的。 测试样例 样例1…

时间类的实现

在现实生活中&#xff0c;我们常常需要计算某一天的前/后xx天是哪一天&#xff0c;算起来十分麻烦&#xff0c;为此我们不妨写一个程序&#xff0c;来减少我们的思考时间。 1.基本实现过程 为了实现时间类&#xff0c;我们需要将代码写在3个文件中&#xff0c;以增强可读性&a…

Leetcode 路径总和

使用递归算法 class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {// 如果节点为空&#xff0c;返回falseif (root null) {return false;}// 如果是叶子节点&#xff0c;检查路径和是否等于目标值if (root.left null && root.right null) …

Linux开发讲课50--- epoll、poll、select的原理和区别

一、什么是epoll&#xff1f; epoll是一种I/O事件通知机制&#xff0c;是linux 内核实现IO多路复用的一个实现。IO多路复用是指&#xff0c;在一个操作里同时监听多个输入输出源&#xff0c;在其中一个或多个输入输出源可用的时候返回&#xff0c;然后对其的进行读写操作。 ep…

MySQL datetime不同长度的影响

MySQL datetime长度的影响 1.背景 MySQL数据库中某张表的某个字段类型设置datetime, 长度为0&#xff0c;在进行插入数据时&#xff0c;MySQL会对该字段进行舍入操作。 2.测试 1.创建一张测试表&#xff0c;里面有两个时间字段都是datetime&#xff0c;但其中一个长度为3 …

数据灾备方案学习

1. 数据灾备 1.1 备份 将数据由一份数据转存为多份数据的过程&#xff0c;即为备份&#xff0c;通常指将数据通过某些手段&#xff0c;将数据存放到其他不同设备中&#xff0c;防止数据丢失。指用户为应用系统产生的重要数据&#xff08;或者原有的重要数据信息&#xff09;制…

在centos7中安装SqlDeveloper的Oracle可视化工具

1.下载安装包 &#xff08;1&#xff09;在SqlDeveloper官网下载&#xff08;Oracle SQL Developer Release 19.2 - Get Started&#xff09;对应版本的安装包即可&#xff08;安装包和安装命令如下&#xff09;&#xff1a; &#xff08;2&#xff09;执行完上述命令后&#x…

矩阵论在深度学习中的应用

摘要&#xff1a; 本文深入探讨了矩阵论在深度学习领域的广泛应用。首先介绍了深度学习中数据表示和模型结构与矩阵的紧密联系&#xff0c;接着详细阐述了矩阵论在神经网络训练算法优化、卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;及其…

AlphaFold 3开源,谷歌DeepMind诺奖AI项目,革新蛋白质结构预测,加速新药和疫苗研发

AlphaFold 3是什么&#xff1f; MeoAI了解到这个模型在2024年因其在蛋白质结构预测方面的贡献获得了诺贝尔化学奖。AlphaFold 3 是由 DeepMind 开发的一款人工智能&#xff08;AI&#xff09;软件&#xff0c;它能够以前所未有的精确度预测几乎所有生命大分子&#xff08;蛋白…

Excel如何把两列数据合并成一列,4种方法

Excel如何把两列数据合并成一列,4种方法 参考链接:https://baijiahao.baidu.com/s?id=1786337572531105925&wfr=spider&for=pc 在Excel中,有时候需要把两列或者多列数据合并到一列中,下面介绍4种常见方法,并且提示一些使用注意事项,总有一种方法符合你的要求:…