JQuery披了一层外衣
jquery是一个轻量级的JS框架,它披了一件外衣,将自己给隐藏了起来。
(function( window, undefined ) { /* 源码内容 */ })
( window );
使用闭包技术,隐藏所有的局部变量,可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行。下面就是一个闭包的使用,实现了一个技术功能,保护内部变量,只有通过函数才可以对变量操作。
<script>
var aa=(function(){
var count = 0;
alert(count);//闭包中的一个重要的关键点是自我调用,运行时只运行一次,这里可对count这个变量做初始化
return function() {
count=count+1;
return count;
}
})();
aa();
aa();
alert(aa());
</script>
如何全局使用
jquery将自己声明的变量全部都用外衣遮盖起来了,而我们平时使用的Jquery和$,却是真真实实的全局变量,这个是从何而来,谜底就在jquery的某一行代码,一般是在文件的末尾。
<script>
(function(window,undefined){
var jquery= function(selector) {
return new jquery.fn.init(selector);
};
jquery.fn = jquery.prototype = {
init:function(selector){
this.obj = window.document.getElementById(selector);
return this;
}
};
jquery.method1 = function() {
alert("hello");
}
window.jquery=window.$=jquery;//将对象交给window的全局变量$或者是jquery
})(window);
$.method1();
</script>
JQuery利器:Selector
jquery的最核心的功能就是选择器。而选择器简单理解的话,其实就是在DOM文档中,寻找一个DOM对象的工具。
首先我们进入jquery源码中,可以很容易的找到jquery对象的声明,看过以后会发现,原来我们的jquery对象就是init对象。
jQuery = function( selector, context )
{
return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery其实就是将DOM对象加了一层包裹,而寻找某个或者若干个DOM对象是由sizzle选择器负责的,它的官方地址是http://sizzlejs.com/,有兴趣的猿友可以去仔细研究下这个基于CSS的选择器。
下面截取的一个jQuery对象的属性和方法截图,方法这里就不提了,对于属性来说,我们最需要关注的只有一个属性,就是[0]属性,[0]其实就是原生的DOM对象。
很多时候,我们在jQuery和DOM对象之间切换时需要用到[0]这个属性。从截图也可以看出,jQuery对象其实主要就是把原生的DOM对象存在了[0]的位置,并给它加了一系列简便的方法。这个索引0的属性我们可以从一小段代码简单的看一下它的由来,下面是init方法中的一小段对DOMElement对象作为选择器的源码。
if ( selector.nodeType ) {
/* 可以看到,这里将DOM对象赋给了jQuery对象的[0]这个位置 */
this.context = this[0] = selector;
this.length = 1;
return this;
}
这一小段代码可以在jquery源码中找到,它是处理传入的选择参数是一个DOM对象的情况。可以看到,里面很明显的将jQuery对象索引0的位置以及context属性,都赋予了DOM对象。
jquery保证加载完成后再执行的ready
实现类似jquery的ready方法的效果我们是可以简单做到的,它的实现原理就是,维护一个函数数组,然后不停的判断DOM是否加载完毕,倘若加载完毕就触发所有数组中的函数。
jquery的扩展实现
jquery的extend方法的原版形式,jquery.extend(deep,target,source1,source2......)
以及 *jquery.fn.extend(deep,target,source1,source2......)。
*参数详解:
*deep:boolean类型,意为是否要深度拷贝
*target:Object类型,意为要扩展的目标对象
*source1:Object类型,意为被扩展的资源对象
*source2....:与source1相同,理论上可以有无限个
扩展$
$.extend(
{
testExtend:function(){
alert('extend success');
} } );
给对象进行扩展
var targetFn = {};//目标对象
//此处targetFn将作为目标对象扩展
$.fn.extend(targetFn,
{
testExtend:function(){
alert('extend success');
}
}
);
another:
var me = {
name:"hill",
sex:"man", //注意,这里我的女朋友,我的属性,也是一个对象
girlFriend:{
name:"secret",
sex:"woman"
}
};//下面首先采用非深度拷贝的方式对我进行扩展
$.extend(me,
{
work:"programmer",//扩展我的工作为程序员
girlFriend:{
work:"rich"//扩展我女朋友的职业为富婆,这是不是若干人群的梦想
}
}
);
/* *是不是发现我女朋友的名字和性别都未知了,这是因为在非深度拷贝的情况下,如 *果属性为对象,将会被扩展的属性值直接覆盖掉,也就是原来的属性name和sex会被直接覆盖,即name和sex会被work覆盖 */
如果换成深度扩展,就没有问题了
$.extend(
true,//深度拷贝
me,
{ work:"programmer",//依然扩展我的工作为程序员
girlFriend:{
name:"secret",//当有相同属性名的时候会被覆盖
work:"manager"//当有多出的属性名的时候会被扩展,扩展我女朋友的职业为经理
}
}
);