jquery 这些小技巧你懂吗

2024-05-09 18:48

本文主要是介绍jquery 这些小技巧你懂吗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

jquery有很多奇淫技巧,它的结构清晰,高内聚、低耦合,兼具优秀的性能与便利的扩展性。

这里仅对其中的一些小技巧做个总结。

 

1、jquery闭包

把当前沙箱需要的外部变量通过函数参数引入进来

只要保证参数对内提供的接口的一致性,你可以随意替换传进来的这个参数

(function(window, undefined) {// jQuery 代码undefined = 20;console.log(undefined);  // 20
})(window);
(function(w, u) {// jQuery 代码console.log(w);  // windowu = 20;console.log(u);  // 20
})(window);
(function(window,undefined) {// jQuery 代码undefined = 20;console.log(undefined); // 20})(window, undefined);undefined = 20;console.warn(undefined); // undefined

 

2、jquery 无 new 构造

// 无 new 构造
// s也能访问jq原型链上的所有方法
var s = $('#test');// 当然也可以使用 new
// q能访问jq原型链上的所有方法
var q = new $('#test');
(function (window, undefined) {var// ...jQuery = function (selector, context) {// 实例化方法 jQuery() 实际上是调用了其拓展的原型方法 jQuery.fn.initreturn new jQuery.fn.init(selector, context, rootjQuery);},// jQuery.prototype 即是 jQuery 的原型,挂载在上面的方法,即可让所有生成的 jQuery 对象使用jQuery.fn = jQuery.prototype = {// 实例化化方法,这个方法可以称作 jQuery 对象构造器init: function (selector, context, rootjQuery) {// ...}},jQuery.fn.init.prototype = jQuery.fn;})(window);

1)使用 $('xxx') 这种实例化方式,其内部调用的是 return new jQuery.fn.init(selector, context, rootjQuery) ,即构造实例是交给 jQuery.fn.init() 方法去完成。

2)将 jQuery.fn.init 的 prototype 属性设置为 jQuery.fn,那么使用 new jQuery.fn.init() 生成的对象的原型对象就是 jQuery.fn ,所以挂载到 jQuery.fn 上面的函数就相当于挂载到 jQuery.fn.init() 生成的 jQuery 对象上,所有使用 new jQuery.fn.init() 生成的对象也能够访问到 jQuery.fn 上的所有原型方法。

3)也就是实例化方法存在这么一个关系链  

  • jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype ;
  • new jQuery.fn.init() 相当于 new jQuery() ;
  • var obj1 = jQuery() 返回的是 new jQuery.fn.init(),var obj2 = new jQuery(),obj1和obj2是相当的,所以我们可以无 new 实例化 jQuery 对象。

 

3、jQuery.fn.extend 与 jQuery.extend

jQuey 内部用extend 方法来扩展静态方法或实例方法, jQuery 插件开发的时候也会用到它。

1)jQuery.extend(object) 为扩展 jQuery 类本身,为类添加新的静态方法;

2)jQuery.fn.extend(object) 给 jQuery 对象添加实例方法,也就是通过这个 extend 添加的新方法,实例化的 jQuery 对象都能使用,因为它是挂载在 jQuery.fn 上的方法(jQuery.fn = jQuery.prototype )。 

1)jQuery.extend(): 把两个或者更多的对象合并到第一个当中,

2)jQuery.fn.extend():把对象挂载到 jQuery 的 prototype 属性,来扩展一个新的 jQuery 实例方法。

也就是说,使用 jQuery.extend() 拓展的静态方法,我们可以直接使用 $.xxx 进行调用(xxx是拓展的方法名),

而使用 jQuery.fn.extend() 拓展的实例方法,需要使用 $().xxx 调用。

jQuery.fn.extend({a: function() {console.log('使用$(xx).xxx调用');}
});jQuery.extend({b: '使用$.xxx调用'
})$().a();
$.b;

需要注意的是这一句 jQuery.extend = jQuery.fn.extend = function() {} ,也就是 jQuery.extend 的实现和 jQuery.fn.extend 的实现共用了同一个方法,但是为什么能够实现不同的功能了,这就要归功于 Javascript 强大(怪异?)的 this 了。

1)在 jQuery.extend() 中,this 的指向是 jQuery 对象(或者说是 jQuery 类),所以这里扩展在 jQuery 上;

2)在 jQuery.fn.extend() 中,this 的指向是 fn 对象,前面有提到 jQuery.fn = jQuery.prototype ,也就是这里增加的是原型方法,也就是对象方法。

 

4、jQuery 的链式调用及回溯

只需要在要实现链式调用的方法的返回结果里,返回 this ,就能够实现链式调用了。

var s = {a: function() {console.log(1);return this;},b: function() {console.log(2);return this;},c: function() {console.log(3);return this;}
};s.a().b().c();

jQuery 完整的链式调用、增栈、回溯通过 return this 、 return this.pushStack() 、return this.prevObject 实现

jQuery.fn = jQuery.prototype = {// 将一个 DOM 元素集合加入到 jQuery 栈// 此方法在 jQuery 的 DOM 操作中被频繁的使用, 如在 parent(), find(), filter() 中// pushStack() 方法通过改变一个 jQuery 对象的 prevObject 属性来跟踪链式调用中前一个方法返回的 DOM 结果集合// 当我们在链式调用 end() 方法后, 内部就返回当前 jQuery 对象的 prevObject 属性pushStack: function (elems) {// 构建一个新的jQuery对象,无参的 this.constructor(),只是返回引用this// jQuery.merge 把 elems 节点合并到新的 jQuery 对象// this.constructor 就是 jQuery 的构造函数 jQuery.fn.init,所以 this.constructor() 返回一个 jQuery 对象// 由于 jQuery.merge 函数返回的对象是第二个函数附加到第一个上面,所以 ret 也是一个 jQuery 对象,这里可以解释为什么 pushStack 出入的 DOM 对象也可以用 CSS 方法进行操作var ret = jQuery.merge(this.constructor(), elems);// 给返回的新 jQuery 对象添加属性 prevObject// 所以也就是为什么通过 prevObject 能取到上一个合集的引用了ret.prevObject = this;ret.context = this.context;// Return the newly-formed element setreturn ret;},// 回溯链式调用的上一个对象end: function () {// 回溯的关键是返回 prevObject 属性// 而 prevObject 属性保存了上一步操作的 jQuery 对象集合return this.prevObject || this.constructor(null);},// 取当前 jQuery 对象的第 i 个eq: function (i) {// jQuery 对象集合的长度var len = this.length,j = +i + (i < 0 ? len : 0);// 利用 pushStack 返回return this.pushStack(j >= 0 && j < len ? [this[j]] : []);}
}

总的来说,

1)end() 方法返回 prevObject 属性,这个属性记录了上一步操作的 jQuery 对象合集;

2)而 prevObject 属性由 pushStack() 方法生成,该方法将一个 DOM 元素集合加入到 jQuery 内部管理的一个栈中,通过改变 jQuery 对象的 prevObject 属性来跟踪链式调用中前一个方法返回的 DOM 结果集合

3)当我们在链式调用 end() 方法后,内部就返回当前 jQuery 对象的 prevObject 属性,完成回溯。

 

5、jQuery方法的重载

// 获取 title 属性的值
$('#id').attr('title');
// 设置 title 属性的值
$('#id').attr('title','jQuery');
function addMethod(obj, name, f) {var old = obj[name];obj[name] = function () {if (f.length === arguments.length) {return f.apply(this, arguments);} else {return old.apply(this, arguments);}}
}var people = {name: ["张三", "李四", "王五"]
};var find0 = function () {return this.name;
};var find1 = function (name) {var arr = this.name;for (var i = 0; i < arr.length; i++) {if (arr[i] === name) {return arr[i] + "在" + i + "位";}}
}function test(a) {console.log('形参个数', test.length);  // 1console.log('实参个数', arguments.length);  // 0
}test();addMethod(people, 'find', find0);
addMethod(people, 'find', find1);
console.log(people.find("王五"));

 

6、jQuery 变量冲突处理

当需要处理冲突的时候,调用静态方法 noConflict(),让出变量的控制权

(function(window, undefined) {var// Map over jQuery in case of overwrite// 设置别名,通过两个私有变量映射了 window 环境下的 jQuery 和 $ 两个对象,以防止变量被强行覆盖_jQuery = window.jQuery,_$ = window.$;jQuery.extend({// noConflict() 方法让出变量 $ 的 jQuery 控制权,这样其他脚本就可以使用它了// 通过全名替代简写的方式来使用 jQuery// deep -- 布尔值,指示是否允许彻底将 jQuery 变量还原(移交 $ 引用的同时是否移交 jQuery 对象本身)noConflict: function(deep) {// 判断全局 $ 变量是否等于 jQuery 变量// 如果等于,则重新还原全局变量 $ 为 jQuery 运行之前的变量(存储在内部变量 _$ 中)if (window.$ === jQuery) {// 此时 jQuery 别名 $ 失效window.$ = _$;}// 当开启深度冲突处理并且全局变量 jQuery 等于内部 jQuery,则把全局 jQuery 还原成之前的状况if (deep && window.jQuery === jQuery) {// 如果 deep 为 true,此时 jQuery 失效window.jQuery = _jQuery;}// 这里返回的是 jQuery 库内部的 jQuery 构造函数(new jQuery.fn.init())// 像使用 $ 一样尽情使用它吧return jQuery;}})
}(window)

jQueryå²çªå¤çæµç¨å¾

 

那么让出了这两个符号之后,是否就不能在我们的代码中使用 jQuery 或者呢 $ 呢?莫慌,还是可以使用的:

// 让出 jQuery 、$ 的控制权不代表不能使用 jQuery 和 $ ,方法如下:
var query = jQuery.noConflict(true);(function($) {// 插件或其他形式的代码,也可以将参数设为 jQuery
})(query);//  ... 其他用 $ 作为别名的库的代码

7、短路表达式

var a = 1, b = 0, c = 3;var foo = a && b && c,    // 0 ,相当于 a && (b && c)bar = a || b || c;   // 1

1、在 Javascript 的逻辑运算中,0、""、null、false、undefined、NaN 都会判定为 false ,而其他都为 true ;

2、因为 Javascript 的内置弱类型域 (weak-typing domain),所以对严格的输入验证这一点不太在意,即便使用 && 或者 || 运算符的运算数不是布尔值,仍然可以将它看作布尔运算。虽然如此,还是建议如下:

if(foo){ ... }     //不够严谨
if(!!foo){ ... }   //更为严谨,!!可将其他类型的值转换为boolean类型

8、$.trim

let core_version = "1.19.2";let core_Trim = core_version.trim;function trim(data) {return core_Trim.call(data);
}
console.log(trim("  abds  "));
// 源码
core_version = "1.9.0",
core_trim = core_version.trim,
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,trim: core_trim && !core_trim.call("\uFEFF\xA0") ?function( text ) {return text == null ?"" :core_trim.call( text );} :// Otherwise use our own trimming functionalityfunction( text ) {return text == null ?"" :( text + "" ).replace( rtrim, "" );}

var core_trim = String.prototype.trim; if (core_trim && !core_trim.call("\uFEFF\xA0")) 相当于: if (String.prototype.trim && "\uFEFF\xA0".trim() !== "") 高级的浏览器已经支持原生的String的trim方法,但是jQuery还为了避免它没法解析全角空白,所以加多了一个判断:"\uFEFF\xA0".trim() !== ""

\uFEFF是utf8的字节序标记,详见:字节顺序标记 "\xA0"是全角空格 如果以上条件成立了,那就直接用原生的trim函数就好了,展开也即是:

$.trim = function( text ) {return text == null ?"" :text.trim();
}

如果上述条件不成立了,那jQuery就自己实现一个trim方法:

$.trim = function( text ) {return text == null ?"" :( text + "" ).replace( rtrim, "" );
}

 

 

参考文章:

【深入浅出jQuery】源码浅析--整体架构

 

 

这篇关于jquery 这些小技巧你懂吗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974199

相关文章

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

如何在Mac上彻底删除Edge账户? 手动卸载Edge浏览器并清理残留文件技巧

《如何在Mac上彻底删除Edge账户?手动卸载Edge浏览器并清理残留文件技巧》Mac上的Edge账户里存了不少网站密码和个人信息,结果同事一不小心打开了,简直尴尬到爆炸,想要卸载edge浏览器并清... 如果你遇到 Microsoft Edge 浏览器运行迟缓、频繁崩溃或网页加载异常等问题,可以尝试多种方

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled