一个很老的话题,只是自己做下记录,免得忘记。写得比较简单还请见谅,有不对的地方也请告知,多谢:) jQuery的版本2.1.1pre
如何生成一个jQuery对象呢?
直接调用$(selector, context)即可,让我们来看看源码都做了什么
// Define a local copy of jQuery
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
},
实例化一个jQuery.fn.init对象(别看那么长的名字,就当成是一个function name就行),那在这个构造函数里都做了什么呢?
init = jQuery.fn.init = function( selector, context ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
if ( !selector ) {
return this;
}
........
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
};
其实就是返回来一个伪数组的自身实例,也就是jQuery.fn.init的实例,这也就是我们常用到的jQuery对象。
那jQuery怎么实现链式语法呢?
我们接着源码往下看,下面这句是关键。
// Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn;
也就是jQuery.fn.init的实例都拥有jQuery.fn相应的方法,也就是我们所使用的方法都在这个上面。那jQuery.fn最开始是什么样的?没有jQuery.fn也就没有jQuery.fn.init。
jQuery.fn = jQuery.prototype = {
// The current version of jQuery being used
jquery: version,
constructor: jQuery,
// Start with an empty selector
selector: "",
// The default length of a jQuery object is 0
length: 0,
toArray: function() {
return slice.call( this );
},
.....................
};
这就是他的赋值来,相当于一个Object对象。那怎么给他新增方法呢?看看他给我们提供了什么?
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( i === length ) {
target = this;
i--;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
通过extend可以扩展方法,其中jQuery.extend是给jQuery扩展方法,这个我的理解他就像一个工具类,比如我们常用的$.each,$.trim等都源自于此。而jQuery.fn.extend则相当于给我们的jQuery对象扩展方法,上下文就是jQuery.fn.init实例对象本身,链式中方法都源自于此。
既然是链式语法,那方法调用后都返回了什么呢?
很显然的就是jQuery对象自身,我们看看removeAttr的实现
jQuery.fn.extend({
attr: function( name, value ) {
return access( this, jQuery.attr, name, value, arguments.length > 1 );
},
removeAttr: function( name ) {
return this.each(function() {
jQuery.removeAttr( this, name );
});
}
});
jQuery.fn = jQuery.prototype = {
.....................
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
.....................
}
从之前的init.prototype = jQuery.fn;可以看出this实际上就是init的实例。
jQuery.extend({
..................................
// args is for internal usage only
each: function( obj, callback, args ) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike( obj );
if ( args ) {
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.apply( obj[ i ], args );
if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.apply( obj[ i ], args );
if ( value === false ) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
}
}
return obj;
},
.....................
}
直接看返回的结果obj, 他就是之前传入的this参数,也就是jQuery.fn.init的实例对象,removeAttr最后调用this.each返回的就是这个对象。这个对象拥有着jQuery.fn上的所有方法,所以我们还能接着调用jQuery的方法。
本文详细解析了jQuery的初始化函数和链式语法实现机制,包括如何生成jQuery对象,jQuery.fn.init实例的作用及jQuery.extend方法的用途。通过实例展示了jQuery对象的创建过程及如何扩展其方法,同时解释了jQuery的链式调用是如何返回自身以实现连贯操作。
1586

被折叠的 条评论
为什么被折叠?



