jQuery源码学习8——工具方法之init
接下来再回到init工具方法
总体看来init里面都是通过jQuery.each方法来遍历macros里面的各项
再将其扩展到jQuery.prototype下面作为实例方法
(1)、axis
jQuery.each( jQuery.macros.axis, function(i,n){ jQuery.fn[ i ] = function(a) { var ret = jQuery.map(this,n); if ( a && a.constructor == String ) ret = jQuery.filter(a,ret).r; return this.pushStack( ret, arguments ); }; });
axis: { parent: "a.parentNode", ancestors: jQuery.parents, parents: jQuery.parents, next: "jQuery.sibling(a).next", prev: "jQuery.sibling(a).prev", siblings: jQuery.sibling, children: "a.childNodes" },
遍历axis时,function里面i就是axis的键,例如parent ancestors
n就是axis里面键对应的值,例如"a.parentNode" jQuery.parents
其实就是将parent ancestors之类的方法扩展到了jQuery.fn(即jQuery.prototype)上了
axis扩展到jQuery.prototype上的方法都传入了一个参数a
接下来通过map方法遍历jQuery对象this
实际上this就是一个类数组对象
map方法的返回值ret存储的就是this里面的各项通过n处理后返回的结果
n又分为字符串和函数两类,通过字符串传入时就传入一个字符串格式的方法体就可以
这些细节都在map方法中已经处理好了
map和each一个很大的区别就是map内部重新定义了一个数组
再用传入的fn处理后push到这个数组里面
最后返回这个数组,这个数组和原来通过map方法处理的json或数组已经没有任何关系了
完全是两个不同的变量
在这里的话就是ret和this没有任何的关系了,之后再对ret修改也不会影响到this了
在调用parent这个方法的时候将会类似$("#div1").parent("xxx")或$("#div1").parent()
(2)to
jQuery.each( jQuery.macros.to, function(i,n){ jQuery.fn[ i ] = function(){ var a = arguments; return this.each(function(){ for ( var j = 0; j < a.length; j++ ) $(a[j])[n]( this ); }); }; });
to: { appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after" },
总体和上面axis差不太多,以appendTo为例
实际上就是类似这样的扩展:
jQuery.prototype.appendTo=function(){ var a = arguments; return this.each(function(){ for ( var j = 0; j < a.length; j++ ) $(a[j])[n]( this ); }); };
这里的n其实就是"append"
调用的时候形如$("<div></div>").appendTo($("#div1"));
意思就是在$("#div1")下添加一个div
其实to里面扩展的方法都有一个"反向添加"的效果
(3)each
jQuery.each( jQuery.macros.each, function(i,n){ jQuery.fn[ i ] = function() { return this.each( n, arguments ); }; });
macros.each下面方法太多了,就不贴代码了
以removeAttr为例,扩展方法的形式为
jQuery.prototype.removeAttr=function(){ return this.each(function( key ) { this.removeAttribute( key ); },arguments); };
在调用时就形如$("#div1").removeAttr("abc");
removeAttr函数体里面的arguments就会接收到"abc"这个参数
即
this.each(function( key ) { this.removeAttribute( key ); },["abc"]);
实例化方法的each最终会调用静态方法jQuery.each
each: function( fn, args ) { return jQuery.each( this, fn, args ); },
调用形式为
jQuery.each(this,function(key){ this.removeAttribute(key); },["abc"]);
最终传入的function会以以下这种方式调用,fn就是指传入的该函数
fn.apply(this[0],["abc"]);
其实这些方法之所以放到一个键叫each的对象当中,就是因为这些方法的内部都会调用each方法
(4)filter
jQuery.each( jQuery.macros.filter, function(i,n){ jQuery.fn[ n ] = function(num,fn) { return this.filter( ":" + n + "(" + num + ")", fn ); }; });
filter: [ "eq", "lt", "gt", "contains" ],
这几个方法就是调用了Sizzle里面的伪类选择器来实现的,例如$(".div").eq(0)会就是要调用this.filter(":eq(0)");
(5)attr
jQuery.each( jQuery.macros.attr, function(i,n){ n = n || i; jQuery.fn[ i ] = function(h) { return h == undefined ? this.length ? this[0][n] : null : this.attr( n, h ); }; });
attr: { val: "value", html: "innerHTML", id: null, title: null, name: null, href: null, src: null, rel: null },
attr里面每一项如果有值的话,这个值是对应的键的修正值,这几个方法都有设置和获取的功能
获取的话会调用attr实例化方法
(6)css
jQuery.each( jQuery.macros.css, function(i,n){ jQuery.fn[ n ] = function(h) { return h == undefined ? ( this.length ? jQuery.css( this[0], n ) : null ) : this.css( n, h ); }; });
css: "width,height,top,left,position,float,overflow,color,background".split(","),
css里面的各个方法底层自然是通过调用css原生方法来实现的