jQuery源码学习(一)
有很长一段时间没有更新博客了,近一段时间开始重新梳理知识点和写博客了。重要的事情说三遍,新的博客地址:欢迎访问,新的博客地址:欢迎访问,新的博客地址:欢迎访问。
jQuery的核心理念
- 简洁的API
- 优雅的链式
- 强大的选择器
- 便捷的操作
jQuery框架的核心就是从HTML文档中匹配元素并对其执行操作
jQuery源码整体放在一个匿名函数执行中
(function(window,undefined){//这里是形参
})(window,undefined);//传入实参
**这样写的好处是:**在匿名函数中定义的变量和函数在匿名函数外部都是访问不到的,在匿名函数中提供对外访问的接口
这里把window当做参数传进来是因为window处于作用域的最顶端,它的查找速度是最慢的。
**好处1:**将window作为实参传递给匿名函数的形参,在匿名函数中可以加快window的查找速度
**好处2:**在压缩版本中window作为实参传递给匿名函数的形参e,通过这样传递,我们知道在压缩代码中e就代表了window
传入undefined,是因为在匿名函数外部undefined可能被修改为其他值,将undefined作为参数传进来,在匿名函数中用到undefined了就是用的传进来的值而不会向外查找了。
方法和属性
####jquery##
用来输出相应的版本号:
<script type="text/javascript">
alert($().jquery);//弹出版本号
</script>
####constructor##
<script type="text/javascript">
function Person(){
}
Person.prototype.name = "lisi";
Person.prototype.age = 20;
var person1 = new Person();
alert(person1.constructor);//输出相应的构造函数
/*
function Person(){
}*/
</script>
<script type="text/javascript">
function Person(){
}
Person.prototype = {//这里是重写了原型,这样构造函数指向就出现了问题,需要手动去修正constructor:Person,name:"lisi",age:20
}
var person1 = new Person();
alert(person1.constructor);
/*
function Object(){[native code]
}*/
</script>
####jQuery对象转为dom对象##
<script type="text/javascript">
console.log($("li"));//jQuery.fn.init[3],每个li都有对应的下标
$("li")[1].style.background = "#f00";//$("li")[1]这样可以把jQuery转化为dom对象
</script>
####parseHTML##
jQuery.parseHTML用来将字符串转化为数组,返回一个数组
<script type="text/javascript">
$(function(){var str = '<li>1</li><li>2</li><li>3</li>';var arr = jQuery.parseHTML(str);console.log(arr);//[li, li, li]$.each(arr,function(i){$("ul").append(arr[i]);});
});
</script>
####merge##
script type="text/javascript">
$(function(){var arr1 = ['a','b'];var arr2 = ['c','d'];var arr3 = {0:'a',1:'b',length:2};//$.merge用来合并数组console.log($.merge(arr1,arr2));//["a", "b", "c", "d"]//$.merge也可以用来合并json//merge在jQuery中可以用来合并jsonconsole.log($.merge(arr3,arr2));//Object {0: "a", 1: "b", 2: "c", 3: "d", length: 4}
});
</script>
####正则匹配##
<script type="text/javascript">var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;var str1 = '#div1';var str2 = '<li>hello';console.log(rquickExpr.exec(str1));//["#div1",undefined,'div1'];console.log(rquickExpr.exec(str2));//["<li>hello", "<li>", undefined]</script>
####makeArray###
<body><div>1</div><div>2</div><div>3</div><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">var oDiv=document.getElementsByTagName("div");/*oDiv只是一个类数组,并不是真正的数组,类数组不能调用数组的方法在jQuery中可以通过makeArray方法将类数组转为真正数组*/console.log(oDiv);//HTMLCollection[div, div, div]console.log($.makeArray(oDiv));//[div, div, div] 变为数组console.log($.makeArray(oDiv,{length:0}));// Object { 0=div, 1=div, 2=div, 更多...} 变为json形式</script>
</body>
####pushStack###
pushStack():JQ对象的入栈栈是后进先出,所以这里span的背景颜色变红队列是先进先出end() 进行出栈操作,来返回栈中的前一个状态
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>pushStack</title>
</head>
<body><div>1111111</div><span>222222</span><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">
$(function(){ $('div').pushStack($('span')).css('background','red');
//end() 进行出栈操作,来返回栈中的前一个状态,所以div背景变黄了 $('div').pushStack($('span')).css('background','red').end().css('background','yellow');});</script>
</body>
</html>
<body><div>1111111</div><div>1111111</div><div>1111111</div><div>1111111</div><span>222222</span><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">$(function(){//$('div').slice(1,3).css('background','red');
//$('div')选择了所有的div
//slice(1,3)选择了中间两个div
//栈中$('div')在下,slice(1,3)在上
//所以css('background','red')使得中间两个div背景变红
//end() 进行出栈操作,返回栈中的前一个状态
//css('color','blue')使得四个div的字体颜色都为蓝色$('div').slice(1,3).css('background','red').end().css('color','blue');});</script>
</body>
####map###
返回新集合
<body><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">var arr=['a','b','c'];//将原始数组中的每个值加上自己索引后,映射到新的数组中。arr=$.map(arr,function(elem,i){//i是数组元素的下标//elem表示数组元素return elem+i;});console.log(arr);// ["a0", "b1", "c2"]</script>
</body>
####eq###
first(就是eq(0))和last(就是eq(-1))方法都是基于eq方法来实现的
<body><div>1111111</div><div>1111111</div><div>1111111</div><div>1111111</div><span>222222</span><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">/*eq是获取指定下标的元素下标可以为负值*/$(function(){//$('div')选择了所有的div//eq(2)选择了第三个div//栈中$('div')在下,eq(2)在上//所以css('color','red')使得第三个div字体颜色变红$('div').eq(2).css('color','red');$('div').eq(-1).css('color','red');//其实是-1+length});</script>
</body>
####toArray()###
toArray()方法用来转数组
<body><div>1</div><div>2</div><div>3</div><script type="text/javascript" src="../jquery-2.1.4.js"></script><script type="text/javascript">$(function(){console.log($('div'));//Object[div, div, div] 返回的是对象console.log($('div').toArray());//[div, div, div] 返回数组});</script>
</body>
extend–JQ的继承方法##
###jQuery.extend和jQuery.fn.extend###
- jQuery.extend 对jQuery本身的属性和方法进行了扩展
- jQuery.fn.extend 对jQuery.fn的属性和方法进行了扩展
jQuery.extend 调用的时候,this是指向jQuery对象的(jQuery是函数,也是对象!),所以这里扩展在jQuery上。
而jQuery.fn.extend 调用的时候,this指向fn对象,jQuery.fn 和jQuery.prototype指向同一对象,扩展fn就是扩展jQuery.prototype原型对象。这里增加的是原型方法,也就是对象方法了。
<body>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">//当只写一个对象字面量的时候,JQ中扩展插件的形式$.extend({//扩展工具方法aaa:function(){alert(1);},bbb:function(){alert(2);}});$.fn.extend({//扩展JQ实例方法aaa:function(){alert(3);},bbb:function(){alert(4);}});
//$代表函数
$.aaa();
$.bbb();
//$()代表对象
$().aaa();
$().bbb();
//$.extend(); this指向$ this.aaa->$.aaa()
//$.fn.extend(); this指向$.fn this.aaa->$().aaa()
//$.fn是原型,在原型下扩展的方法,需要通过对象实例来调用
</script>
</body>
<body>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">//当写多个对象字面量的时候,后面的对象都是扩展到第一个对象身上var a={};$.extend(a,{name:'hello'},{age:30});console.log(a);// Object { name="hello", age=30}
</script>
</body>
<body>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">//当写多个对象字面量的时候,后面的对象都是扩展到第一个对象身上//还可以做深拷贝和浅拷贝//默认是浅拷贝var a={};var b={name:"hello"};$.extend(a,b);//浅拷贝a.name='hi';console.log(b.name);//hello//当进行浅拷贝的时候b.name.age会受影响,这时就需要深拷贝var a={};var b={name:{age:30}};$.extend(a,b);//浅拷贝a.name.age=20;console.log(b.name.age);//20var a={};var b={name:{age:30}};$.extend(true,a,b);//深拷贝a.name.age=20;console.log(b.name.age);//30/*JQ:拷贝继承*/
</script>
</body>
###jQuery.extend()用法###
**Demo1:**这个例子只给jQuery.extend()方法传递了一个对象参数,这样会将该对象的所有属性和方法添加到jQuery对象上。
<script type="text/javascript" src="jquery-2.1.4.js"></script>
<script type="text/javascript">
$(function(){var obj1 = {apple:0,banana:{weight:52,price:100},cherry:97};$.extend(obj1);//这样写是将obj1对象的属性添加给jQuery对象console.log(jQuery.apple);//0console.log(jQuery.banana);//Object {weight: 52, price: 100}console.log(jQuery.cherry);//97
});
</script>
Demo2:
<script type="text/javascript" src="jquery-2.1.4.js"></script>
<script type="text/javascript">
$(function(){var obj1 = {apple:0,banana:{weight:52,price:100},cherry:97};var obj2 = {banana:{price:200},durian:100};var obj = $.extend(obj1,obj2);console.log(JSON.stringify(obj));//{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}//从输出的结果可以看出,banana这个key值被替换掉了
});
</script>
**Demo3:**深拷贝
<script type="text/javascript" src="jquery-2.1.4.js"></script>
<script type="text/javascript">
$(function(){var obj1 = {apple:0,banana:{weight:52,price:100},cherry:97};var obj2 = {banana:{price:200},durian:100};var obj = $.extend(true,obj1,obj2);//第一个参数true表示深拷贝console.log(JSON.stringify(obj));//{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}//深拷贝是进行递归合并,对已有属性值进行覆盖替换,没有的属性进行增加//{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
});
</script>
一篇不错的博文:jQuery.extend 函数详解
jQuery.extend()–扩展一些工具方法
###noConflict()###
jQuery与其他库的防冲突解决
<body>
<div>1111111</div>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">var aa = $.noConflict();//这里在引入jQuery库之后使用了$//这样就会导致$成为123,而不是原先的jQuery函数,所以要在这之前调用处理冲突函数,将$对jQuery的引用解除,并将jQuery对象赋值给aa变量console.log(window.$);//undefinedvar $ = 123;aa(function(){alert($);//123});
</script>
</body>
在jQuery库之前引用$和jQuery
<body>
<script type="text/javascript">
/*
源码中:
_jQuery = window.jQuery
_$ = window.$*/
//这里在引入jQuery之前将$赋值为123
//相当于将jQuery源码中的_$ = window.$ = 123var $ = 123;
//相当于将jQuery源码中的_jQuery = window.jQuery = 456var jQuery = 456;//console.log("window:"+window.$);//window:123
</script>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">var aa = $.noConflict(true);//这里aa就等于$.noConflict()函数返回的jQuery对象aa(function(){alert($);//123alert(jQuery);//456});
</script>
</body>
上面代码中在引入jQuery库之前,先将$
和jQuery分别赋值。并在jQuery源码中分别将其值保存在私有变量_$
和_jQuery中。
当我们引入jQuery库之后:
window.jQuery = window.$ = jQuery;
这样一来,之前$
和jQuery的值将被覆盖为jQuery对象。如果不进行冲突处理,将无法访问之前定义的$
和jQuery。当使用jQuery防冲突方法后,用我们之前保存在私有变量_$
和_jQuery中的值重新给$
和jQuery赋值,并将jQuery对象赋值给其他变量。这样一来我们就能够正常访问$
和jQuery了。
jQuery在其他库之后引入
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>jQuery与其他库的冲突解决</title>
</head>
<body><div id="box1">Test-prototype(将被隐藏)</div><div id="box2">Test-jQuery(将被绑定单击事件)</div><script type="text/javascript" src="http://apps.bdimg.com/libs/prototype/1.7.1.0/prototype.js"></script><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript">jQuery.noConflict();//将变量$的控制权移交给prototype.jsjQuery(function(){//使用jQueryjQuery("#box2").click(function(){alert(jQuery(this).text())});});$("box1").style.display = 'none';//使用prototype.js隐藏元素//这样就可以将jQuery函数作为jQuery对象的制造工厂</script>
</body>
</html>
由于prototype和jQuery中都存在$
引用,而jQuery在prototype之后引入,这样一来会导致prototype中的$
无法使用。所以,这里我们jQuery的防冲突方法,使得jQuery放弃了$
。这样一来,就可以在prototype中正常使用$
了。
注意:
window.jQuery = window.$ = jQuery;
这里虽然jQuery放弃了$
,但是可以使用window.jQuery来使用jQuery对象。
自定义快捷方式
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>jQuery与其他库的冲突解决</title>
</head>
<body><div id="box1">Test-prototype(将被隐藏)</div><div id="box2">Test-jQuery(将被绑定单击事件)</div><script type="text/javascript" src="http://apps.bdimg.com/libs/prototype/1.7.1.0/prototype.js"></script><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript">$j = jQuery.noConflict();//将变量$的控制权移交给prototype.js$j(function(){//使用jQuery$j("#box2").click(function(){alert($j(this).text())});});$("box1").style.display = 'none';//使用prototype.js隐藏元素//这样就可以将jQuery函数作为jQuery对象的制造工厂</script>
</body>
</html>
如果不想给jQuery自定义备用名称,还想使用而不管其他库的而不管其他库的而不管其他库的()方法,同时又不想与其他库相冲突,我们可以这样来解决
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>jQuery与其他库的冲突解决</title>
</head>
<body><div id="box1">Test-prototype(将被隐藏)</div><div id="box2">Test-jQuery(将被绑定单击事件)</div><script type="text/javascript" src="http://apps.bdimg.com/libs/prototype/1.7.1.0/prototype.js"></script><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript">jQuery.noConflict();//将变量$的控制权移交给prototype.js(function($){//定义匿名函数并设置形参$$(function(){//匿名函数内部的$均为jQuery$("#box2").click(function(){//继续使用$()方法alert($(this).text())});});})(jQuery);//执行匿名函数且传递实参jQuery$("box1").style.display = 'none';//使用prototype.js隐藏元素</script>
</body>
</html>
jQuery在其他库之前引入
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>jQuery与其他库的冲突解决</title>
</head>
<body><div id="box1">Test-prototype(将被隐藏)</div><div id="box2">Test-jQuery(将被绑定单击事件)</div><script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript" src="http://apps.bdimg.com/libs/prototype/1.7.1.0/prototype.js"></script><script type="text/javascript">//jQuery库在其他库之前引入了,可以直接使用jQuery,无需调用jQuery.noConflict(),可以使用$()方法作为其他库的快捷方式jQuery(function(){//直接使用jQuery,无需调用jQuery.noConflict()jQuery("#box2").click(function(){alert(jQuery(this).text())});});$("box1").style.display = 'none';//使用prototype.js隐藏元素//这样就可以将jQuery函数作为jQuery对象的制造工厂</script>
</body>
</html>
相应的源码:
//防止冲突noConflict: function( deep ) {if ( window.$ === jQuery ) {window.$ = _$;//将私有变量_$赋值给对外接口window.$,这里jQuery就放弃了$}//当传递参数的时候if ( deep && window.jQuery === jQuery ) {window.jQuery = _jQuery;//将私有变量_jQuery赋值给对外接口window.jQuery,这里jQuery就放弃了jQuery}return jQuery;}
###expando###
expando用来生成一个随机字符串
在数据缓存、事件操作、aJax都用到这个来生成随机字符串
<body>
<script type="text/javascript" src="../../jquery-2.1.4.js"></script>
<script type="text/javascript">
//生成一个随机字符串
console.log($.expando);//jQuery214073688220245906
</script>
</body>
待续。。。
jQuery源码学习(一)相关推荐
- jQuery源码学习之Callbacks
jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...
- jquery源码学习笔记三:jQuery工厂剖析
jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...
- jQuery源码学习(1)——addClass
最近比较闲,寻思着学习下jQuery源码,看了好多博客,很多都讲的比较详细.jQuery虽然只有那么200多K,但内容却比较丰富,对于我这样一个js菜鸟,看起来相当吃力.骨头太大,只能化整为零,从简单 ...
- jquery源码学习笔记一:总体结构
练武不练功,到老一场空.计算机也一样. 计算机的功,就是原理.如果程序员只会使用各种函数,各种框架,而不知其原理,顶多熟练工人而已.知其然,更要知其所以然. jquery我们用得很爽,但它究竟咋实现的 ...
- jQuery源码学习
$.jQuery是什么? 平时天天在用的$到底是个什么东西?$("id")思考,感觉像个工厂方法.提供selector创建jquery对象. 一看源码绕晕了,剥茧抽丝吧 定义jqu ...
- jQuery源码学习第二天--jQuery的extend扩展
Jquery中的extend扩展 一.看下常见的extend扩展: 1: jQuery.extend({ 2: noConflict: function( deep ) { 3: if ( windo ...
- jQuery源码学习(6)-Sizzle选择器(2)
1.CSS选择器的位置关系: 四种关系:"+" 紧挨着的兄弟关系:">" 父子关系:" " 祖先关系:"~" 之后 ...
- jQuery源码学习(5)-Sizzle选择器(1)
1.常见的选择器: #test表示id为test的DOM节点 .aaron 表示class为aaron的DOM节点 nav>li 表示在nav内部子li的样式,而不是所有的后代元素,只是往下一层 ...
- 通过jQuery源码学习javascript(三)
序 承接上两篇继续写下去.我尽量把我明白的地方给大家说清楚.有些大家的提问我也有点搞不明白,如果有人能解答,再好不过了. 疑问 第一篇中有位博友提出了以下的问题,我也不太明白,如果有明白的,能否告知一 ...
- jQuery源码学习视频
为什么80%的码农都做不了架构师?>>> http://bbs.miaov.com/forum.php?mod=viewthread&tid=7385&extr ...
最新文章
- JVM内幕:Java虚拟机详解
- Delphi中的堆,栈
- pdd本质上来说,没有什么壁垒
- andorid之设置竖横屏自适应以及角度获取
- 豆瓣9.4!《深度学习入门》笔记总结,带你从感知机入门深度学习!(连载)...
- Nginx笔记(一):安装
- JS生成验证码、卡密,生成指定位数的字符串
- AV1视频编解码器核心编码工具概述
- leetcode69 x的平方根
- USACO 4.2 The Perfect Stall 完美的牛栏(最大匹配)
- 深度长文探讨Join运算的简化和提速
- 小小明_小小明手游框架_xxm_小小明手游平台
- 解决方案:Zotero+坚果云+Zotfile完成多平台多设备的文献同步
- 2022年一级建造师考试《市政公用工程》练习题及答案(多选题)
- 扫 雷 小 游 戏
- 【算法】3 由招聘问题看随机算法
- 换个角度看“量子技术”,它离我们可能不再遥远
- 软件测试相关术语及其含义
- unity入门精要之第6 章 Unity 中的基础光照概述-1
- 红酒、白酒数据集分析——案例(1)