第一篇提到了jquery的核心部分就在于自执行函数传入的第二个参数,factory,其实就是一个函数。jquery的源码一万多行,一点点顺着读下去把。
function( window, noGlobal ) {
"use strict";
//拿到数组和对象的原生方法
var arr = [];
var document = window.document;
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
var concat = arr.concat;
var push = arr.push;
var indexOf = arr.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
var ObjectFunctionString = fnToString.call( Object );
var support = {};
function DOMEval( code, doc ) {
doc = doc || document;
var script = doc.createElement( "script" );
script.text = code;
doc.head.appendChild( script ).parentNode.removeChild( script );
}
//这个函数很有意思建一个script标签,把传入的code塞进script标签,把这个script标签塞插入到document里面然后又立即移除这个script标签。看起来这个函数像是把一段代码在全局中立即调用然后又从全局中立即销毁。后面遇到调用这个函数,再回头看。
/* global Symbol */
// Defining this global in .eslintrc.json would create a danger of using the global
// unguarded in another place, it seems safer to define global only for this module
//这里开始定义jquery相关的东西
var
version = "3.2.1",//版本号
// 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的核心,在源码的最后jquery又赋值给$,所以每次用jquery('#id')或者是$('#id')的时候,都是直接调用这个方法。该方法返回一个jQuery.fn.init的一个实例。
// Support: Android <=4.0 only
// Make sure we trim BOM and NBSP
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
// Matches dashed string for camelizing
rmsPrefix = /^-ms-/,
rdashAlpha = /-([a-z])/g,
//正则不太懂
// Used by jQuery.camelCase as callback to replace()
fcamelCase = function( all, letter ) {
return letter.toUpperCase();
};
//这种把字符串变成大写的小函数,用到再回头看
//上面jquery的方法中用到jquery.fn,可以看到jquery.fn其实就是jQuery这个构造函数的原型,看看原型中大致定义了什么
jQuery.fn = jQuery.prototype = {
// The current version of jQuery being used
jquery: version, //这种定义在原型上的属性和方法,在有引入jQuery文件的网页中,用jQuery.prototype就能访问到
constructor: jQuery, //原型用对象形式完全重写,要把constructor这个属性重新指向jQuery
// The default length of a jQuery object is 0
length: 0,
toArray: function() {
return slice.call( this );
},
// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function( num ) {
// Return all the elements in a clean array
if ( num == null ) {
return slice.call( this );
}
// Return just the one element from the set
return num < 0 ? this[ num + this.length ] : this[ num ];
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems ) {
// Build a new jQuery matched element set
var ret = jQuery.merge( this.constructor(), elems );
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
// Return the newly-formed element set
return ret;
},
// Execute a callback for every element in the matched set.
each: function( callback ) {
return jQuery.each( this, callback );
},
map: function( callback ) {
return this.pushStack( jQuery.map( this, function( elem, i ) {
return callback.call( elem, i, elem );
} ) );
},
slice: function() {
return this.pushStack( slice.apply( this, arguments ) );
},
first: function() {
return this.eq( 0 );
},
last: function() {
return this.eq( -1 );
},
eq: function( i ) {
var len = this.length,
j = +i + ( i < 0 ? len : 0 );
return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
},
end: function() {
return this.prevObject || this.constructor();
},
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
sort: arr.sort,
splice: arr.splice
//上面定义了很多方法,像常用的eq,get之类的,具体内容先不解释,目前主线是先找到jQuery.fn.init是怎么定义的,这个才是jquery构造函数的核心所在。
};
本章讲了jquery构造函数,以及在构造函数的原型上的方法。下一章说一下extend这个方法。