jquery1.5.1 animate方法:
 
animate: function( prop, speed, easing, callback ) { 
if ( jQuery.isEmptyObject( prop ) ) { 
return this.each( optall.complete ); 
} 
//#7864行this.options.complete.call( this.elem )使得其可以不断的连续执行动画,比如$(‘selector').animate({prop1},speed1).animate({prop2},speed2)这样的动画队列; 
return this[ optall.queue === false ? "each" : "queue" ](function() { 
// XXX 'this' does not always have a nodeName when running the 
// test suite 
var opt = jQuery.extend({}, optall), p, 
isElement = this.nodeType === 1, 
hidden = isElement && jQuery(this).is(":hidden"), 
self = this; 
//要执行动画的prop,prop一般是一个plainObj,形如{key1:value1,key2:value2}; 
for ( p in prop ) { 
//驼峰改写,有些比如magrin-top需要变成驼峰的属性即变成marginTop;见cameCase方法; 
var name = jQuery.camelCase( p ); 
//fix属性;主要是前面camelcase的属性; 
if ( p !== name ) { 
prop[ name ] = prop[ p ]; 
delete prop[ p ]; 
p = name; 
} 
//如果执行$(..).show||$(..).hide;如果这个元素本身是hidden,而动画里面又写hide,直接运行callbacks就可以了; 
if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) { 
return opt.complete.call(this); 
} // www.jb200.com
//如果prop[key]==(height||width)并且是一个dom元素;需要有些特殊的处理; 
if ( isElement && ( p === "height" || p === "width" ) ) { 
// Make sure that nothing sneaks out 
// Record all 3 overflow attributes because IE does not 
// change the overflow attribute when overflowX and 
// overflowY are set to the same value 
opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
// Set display property to inline-block for height/width 
// animations on inline elements that are having width/height 
// animated 
if ( jQuery.css( this, "display" ) === "inline" && 
jQuery.css( this, "float" ) === "none" ) { 
if ( !jQuery.support.inlineBlockNeedsLayout ) { 
this.style.display = "inline-block";
} else { 
var display = defaultDisplay(this.nodeName);
// inline-level elements accept inline-block; 
// block-level elements need to be inline with layout 
if ( display === "inline" ) { 
this.style.display = "inline-block";
} else { 
this.style.display = "inline"; 
this.style.zoom = 1; 
} 
} 
} 
} 
//如果prop[key]是一个数组;只用第一个值prop[p][0]; 
if ( jQuery.isArray( prop[p] ) ) { 
// Create (if needed) and add to specialEasing 
(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1]; 
prop[p] = prop[p][0]; 
} 
}
if ( opt.overflow != null ) { 
//如果动画元素的overflow已经被设置的情况下,把它暂时为hidden; 
this.style.overflow = "hidden"; 
} 
//当前动画键值对,其实就是prop; 
opt.curAnim = jQuery.extend({}, prop); 
//这里便是动画的核心了,对每一个prop[key]进行处理; 
jQuery.each( prop, function( name, val ) { 
//获取一个Fx对象;传入的每一个参数都被设置成为这个对象的属性;其中self是指动画元素自身;opt是前面产生的对象; 
var e = new jQuery.fx( self, opt, name ); 
//当执行show||hide操作的时候prop==fxAttrs(参见show||hide方法) 
if ( rfxtypes.test(val) ) { 
e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop ); 
} else { 
var parts = rfxnum.exec(val), 
//start保存了初始值,它可能在style,也可能在css中,如果该值==null,undefiend,auto,0等将被设置为0; 
start = e.cur(); 
if ( parts ) { 
//end是指变化量的大小,比如:{left:-=66px},那么end=66; 
var end = parseFloat( parts[2] ), 
//单元运算符,就是px,%;如果是一些不能带单位的,比如z-index,设置为空,否则就设置为px; 
unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" ); 
// We need to compute starting value 
//如果不是px,比如%,em等等; 
if ( unit !== "px" ) { 
//设置该属性值name为(end || 1) + unit,如果end=0;设置为1;开始值被设置为start = ((end || 1) / e.cur()) * start; 
jQuery.style( self, name, (end || 1) + unit); 
//这里e.cur()和前面的start = e.cur();是不一样的,因为jQuery.style( self, name, (end || 1) + unit)的执行使得start被改变;用于处理end=0的情况;因为e.cur()作为除数,不能为0; 
start = ((end || 1) / e.cur()) * start; 
jQuery.style( self, name, start + unit); 
}
// If a +=/-= token was provided, we're doing a relative animation 
if ( parts[1] ) { 
//end相应的被设置为运算后的变量值; 
end = ((parts[1] === "-=" ? -1 : 1) * end) + start; 
} 
e.custom( start, end, unit ); 
//如果没有数字化的运算;那么没传入的只能是''; 
} else { 
e.custom( start, val, "" ); 
} 
} 
});
// For JS strict compliance 
return true; 
}); 
},