jQuery源码学习
Posted 自由2017
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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中可以用来合并json
console.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);//20
var 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()–扩展一些工具方法
noConflict()
jQuery与其他库的防冲突解决
<body>
<div>1111111</div>
<script type="text/javascript" src="../jquery-2.1.4.js"></script>
<script type="text/javascript">
var aa = $.noConflict();
var $ = 123;
aa(function(){
alert($);//123
});
</script>
</body>
在jQuery库之前引用$和jQuery
<body>
<script type="text/javascript">
/*
源码中:
_jQuery = window.jQuery
_$ = window.$
*/
//这里在引入jQuery之前将$赋值为123
//相当于将jQuery源码中的_$ = window.$ = 123
var $ = 123;
//相当于将jQuery源码中的_jQuery = window.jQuery = 456
var 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(function(){
alert($);//123
alert(jQuery);//456
});
</script>
</body>
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
jQuery(function(){//使用jQuery
jQuery("#box2").click(function(){
alert(jQuery(this).text())
});
});
$("box1").style.display = ‘none‘;//使用prototype.js隐藏元素
//这样就可以将jQuery函数作为jQuery对象的制造工厂
</script>
</body>
</html>
自定义快捷方式
<!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>
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或zepto源码有哪些写的好的地方?