在 jQuery 框架中,jQuery 对象是一个很奇怪的概念,具有多重身份,所以很多初学者一听说 jQuery 对象就感觉很是不解,误以为它是 John Resig 制造的新概念。我们可以对jQuery 对象进行如下分解。
第一,jQuery 对象是一个数据集合,它不是一个个体对象。因此,你无法直接使用 JavaScript 的方法来操作它。
第二,jQuery 对象实际上就是一个普通的对象,因为它是通过 new 运算符创建的一个新的实例对象。它可以继承原型方法或属性,同时也拥有 Object 类型的方法和属性。
第三,jQuery 对象包含数组特性,因为它赋值了数组元素,以数组结构存储返回的数据。我们可以以 JavaScript 的概念理解 jQuery 对象,例如下面的示例。
- <scripttype="text/javascript">
- varjquery={//定义对象直接量
- name:"jQuery",//以属性方式存储信息
- value:"1.3.2"
- };
- jquery[0]="jQuery";//以数组方式存储信息
- jquery[1]="1.3.2";
- alert(jquery.name);//返回"jQuery"
- alert(jquery[0]);//返回"jQuery"
- this.length=0;//否则,设置实例的length属性值为0
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- },
- html:function(val){//模仿jQuery框架中的html()方法,为匹配的每一个DOM元素插入html代码
- jQuery.each(this,function(val){//调用jQuery.each()工具函数,为每一个DOM元素执行回调函数
- this.innerHTML=val;
- },val);
- },
- jquery:"1.3.2",//原型属性
- size:function(){//原型方法
- returnthis.length;
- }
- };
- jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
- //扩展jQuery工具函数
- jQuery.each=function(object,callback,args){
- for(vari=0;i<object.length;i++){
- callback.call(object[i],args);
- }
- returnobject;
- };
- $("div").html("测试代码");
-
// 扩展 jQuery 对象方法
show: function(speed, callback){},
hide: function(speed, callback){},
toggle: function(fn, fn2){},
fadeTo: function(speed, to, callback){},
animate: function(prop, speed, easing, callback){},
stop: function(clearQueue, gotoEnd){}
});
这样做的好处是什么呢?
extend() 函数能够方便用户快速扩展 jQuery 框架的功能,但是不会破坏 jQuery 框架的原型结构,从而避免后期人工手动添加工具函数或者方法破坏 jQuery 框架的单纯性,同时也方便管理。如果不需要某个插件,只需要简单地删除即可,而不需要在 jQuery 框架源代码中去筛选和删除。
extend() 函数的功能实现起来也很简单,它只是把指定对象的方法复制给 jQuery 对象或者 jQuery.prototype 对象。例如,在下面的示例中,我们为 jQuery 类和原型定义了一个扩展功能的函数 extend() ,该函数的功能很简单,它能够把指定参数对象包含的所有属性复制给 jQuery 或者 jQuery.prototype 对象,这样就可以在应用中随时调用它,并动态扩展 jQuery 对象的方法。
- <div>
- this.length=0;//否则,设置实例的length属性值为0
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- },
- jquery:"1.3.2",//原型属性
- size:function(){//原型方法
- returnthis.length;
- }
- };
- jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
- //jQuery功能扩展函数
- jQuery.extend=jQuery.fn.extend=function(obj){
- for(varpropinobj){
- this[prop]=obj[prop];
- }
- returnthis;
- };
- //扩展jQuery对象方法
- jQuery.fn.extend({
- test:function(){
- alert("测试扩展功能");
- }
- });
- //测试代码
- $("div").test();
-
type: "GET",
url: "test.js",
dataType: "script"
});
使用对象直接量作为参数进行传递,方便参数管理。当方法或者函数的参数长度不固定时,使用对象直接量作为参数存在很多优势。例如,对于下面的用法,ajax()函数就需要进行更加复杂的参数排查和过滤。
$.ajax("GET", "test.js", "script");
如果 ajax() 函数的参数长度是固定的,且是必须的,那么通过这种方式进行传递也就无所谓了,但是如果参数的个数和排序是动态的,那么使用 $.ajax("GET", "test.js", "script"); 这种方法是无法处理的。而 jQuery 框架的很多方法都包含大量的参数,且都是可选的,位置也没有固定要求,所以使用对象直接量是惟一的解决方法。
使用对象直接量作为参数传递的载体,这里就涉及参数处理问题。如何解析并提出参数?如何处理参数和默认值?我们可以通过下面的方法来实现。
- <scripttype="text/javascript">
- var$=jQuery=function(selector,context){//定义类
- returnnewjQuery.fn.init(selector,context);//返回选择器的实例
- };
- jQuery.fn=jQuery.prototype={//jQuery类的原型对象
- init:function(selector,context){//定义选择器构造器
- selector=selector||document;//设置默认值为document
- context=context||document;//设置默认值为document
- if(selector.nodeType){//如果选择符为节点对象
- this[0]=selector;//把参数节点传递给实例对象的数组
- this.length=1;//并设置实例对象的length属性,定义包含的元素个数
- this.context=selector;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- if(typeofselector==="string"){//如果选择符是字符串
- vare=context.getElementsByTagName(selector);//获取指定名称的元素
- for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
- this[i]=e[i];
- }
- this.length=e.length;//设置实例的length属性,即定义包含的元素个数
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }else{
- this.length=0;//否则,设置实例的length属性值为0
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- },
- setOptions:function(options){
- this.options={//方法的默认值,可以扩展
- StartColor:"#000",
- EndColor:"#DDC",
- Step:20,
- Speed:10
- };
- jQuery.extend(this.options,options||{});//如果传递参数,则覆盖原默认参数
- },
- jquery:"1.3.2",//原型属性
- size:function(){//原型方法
- returnthis.length;
- }
- };
- jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
- jQuery.extend=jQuery.fn.extend=function(destination,source){//重新定义extend()函数
- for(varpropertyinsource){
- destination[property]=source[property];
- }
- returndestination;
- };
- returnnewjQuery.fn.init(selector,context);
- };
-
alert("观察我什么时候出现");
})();
这是一个典型的匿名函数基本形式。为什么要用到匿名函数呢?
这时就要进入正题了,如果希望自己的 jQuery 框架与其他任何代码完全隔离开来,也就是说如果你想把 jQuery 装在一个封闭空间中,不希望暴露内部信息,也不希望别的代码随意访问,匿名函数就是一种最好的封闭方式。此时我们只需要提供接口,就可以方便地与外界进行联系。例如,在下面的示例中分别把 f1 函数放在一个匿名函数中,而把 f2 函数放在全局作用域中。可以发现,全局作用域中的 f2 函数可以允许访问,而匿名函数中的 f1 函数是禁止外界访问的。
- <scripttype="text/javascript">
- (function(){
- functionf1(){
- return"f1()";
- }
- })();
- functionf2(){
- return"f2()";
- }
- alert(f2());//返回"f2()"
- alert(f1());//抛出异常,禁止访问
- var
- window=this,
- undefined,
- _jQuery=window.jQuery,//暂存jQuery变量内容
- _$=window.$,//暂存$变量内容
- jQuery=window.jQuery=window.$=function(selector,context){
- returnnewjQuery.fn.init(selector,context);
- },
- quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
- isSimple=/^.[^:#\[\.,]*$/;
- jQuery.fn=jQuery.prototype={
- init:function(selector,context){//定义选择器构造器
- selector=selector||document;//设置默认值为document
- context=context||document;//设置默认值为document
- if(selector.nodeType){//如果选择符为节点对象
- this[0]=selector;//把参数节点传递给实例对象的数组
- this.length=1;//并设置实例对象的length属性,定义包含的元素个数
- this.context=selector;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- if(typeofselector==="string"){//如果选择符是字符串
- vare=context.getElementsByTagName(selector);//获取指定名称的元素
- for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
- this[i]=e[i];
- }
- this.length=e.length;//设置实例的length属性,即定义包含的元素个数
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }else{
- this.length=0;//否则,设置实例的length属性值为0
- this.context=context;//设置实例的属性,返回选择范围
- returnthis;//返回当前实例
- }
- },
- setOptions:function(options){
- this.options={//方法的默认值,可以扩展
- StartColor:"#000",
- EndColor:"#DDC",
- Step:20,
- Speed:10
- };
- jQuery.extend(this.options,options||{});//如果传递参数,则覆盖原默认参数
- },
- jquery:"1.3.2",//原型属性
- size:function(){//原型方法
- returnthis.length;
- }
- };
- jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
- jQuery.extend=jQuery.fn.extend=function(destination,source){//重新定义extend()函数
- for(varpropertyinsource){
- destination[property]=source[property];
- }
- returndestination;
- };
- })();
-
关注打赏
立即登录/注册微信扫码登录