jquery 原理

/*
* my-jquery-1.0
*/
/*
* 網上也有不少實現的版本,不過這是我在我本身的理解下寫的,加上註釋,但願能夠解釋清楚。
*/
/*
* 整個jquery包含在一個匿名函數中,專業點叫閉包,就是下面的形式,如(function(window,undefined){}(window))。
* 閉包的定義在這裏不太容易講清楚,我只說下這樣說的好處。
* 1.使整個jquery中定義的變量成爲局域變量,不會影響全局變量,我的以爲這也是jquery被成爲輕量級的緣由之一。
* 2.增長jquery運行速度,由於局域變量運行速度高於全局變量。
* 3.就像你看到,傳入的window和undefined,能夠自定義名字,方便編寫。固然,如今你看到的還是原來的寫法,可是你能夠看看jquery的min版本,必定是壓縮的。
*/
(function( window, undefined ) {
var
/*jquery的定義,咱們平時用的$和jQuery就是它。這裏能夠看出來真正的jQuery的對象是init方法產生的。
*這樣作採用了工廠模式,建立jQuery對象時不須要再new一個對象了。因此你能夠發現,咱們建立jQuery對象的方式是$(selector)或者是jQuery(selector)
*原版的jQuery定義方法多了個上下文參數context,此處我省略了。
*/
jQuery = function(selector){
return new jQuery.fn.init(selector);
},
/*
* 引用數據、對象以及字符串的方法
*/
core_push = Array.prototype.push,
core_slice = Array.prototype.slice,
core_indexOf = Array.prototype.indexOf,
core_toString = Object.prototype.toString,
core_hasOwn = Object.prototype.hasOwnProperty,
core_trim = String.prototype.trim;
/*
* jQuery對象的定義,這裏去掉了全部的屬性,只留下了init()。
* jQuery的選擇器採用了Sizzle,這裏省略了,能夠看出我只簡單的返回了一個查詢ID的方式。
* jQuery的對象並非這樣簡單的賦給了對象的一個屬性,而是建立了一個數組。在這裏忽略那些,只是賦給了obj屬性。
* 這裏jQuery將原型賦給了jQuery的fn屬性,因此咱們若是要給jQuery對象擴展,只須要對jQuery.fn擴展就行。
*/
jQuery.fn = jQuery.prototype = {
init:function(selector){
this.obj = window.document.getElementById(selector);
return this;
}
};
/*
* 將jQuery的原型賦給init,這樣是爲了可讓jQuery對象,也就是init對象可使用jQuery的擴展方法。
*/
jQuery.fn.init.prototype = jQuery.fn;
/*
* jQuery的擴展方法,這個是jQuery的原版方法,我沒作更改。
* 方法的邏輯在這裏再也不說明,方法的效果就是,咱們使用jQuery.extend能夠擴展jQuery,而jQuery.fn.extend能夠擴展jQuery對象。
*/
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;javascript

// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}html

// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !d.isFunction(target) ) {
target = {};
}java

// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}node

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 ];jquery

// Prevent never-ending loop
if ( target === copy ) {
continue;
}數組

// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( d.isPlainObject(copy) || (copyIsArray = d.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && d.isArray(src) ? src : [];閉包

} else {
clone = src && d.isPlainObject(src) ? src : {};
}函數

// Never move original objects, clone them
target[ name ] = d.extend( deep, clone, copy );工具

// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}oop

// Return the modified object
return target;
};
/*
* 這裏實現了簡單的ready綁定序列。
*/
jQuery.extend({
isReady:false,//文檔加載是否完成的標識
readyList:[],//函數序列
//如下爲工具方法,可忽略
isArray : Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
},

isWindow : function( obj ) {
return obj != null && obj == obj.window;
},

isNumeric : function( obj ) {
return !isNaN( parseFloat(obj) ) && isFinite( obj );
},

type : function( obj ) {
return obj == null ?
String( obj ) :
class2type[ core_toString.call(obj) ] || "object";
},

isPlainObject : function( obj ) {
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}

try {
// Not own constructor property must be Object
if ( obj.constructor &&
!core_hasOwn.call(obj, "constructor") &&
!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}

// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.

var key;
for ( key in obj ) {}

return key === undefined || core_hasOwn.call( obj, key );
},
isFunction : function(obj){
if(obj && typeof obj == 'function'){
return true;
}
return false;
},
//onload事件實現
ready : function(fn){
//若是是函數,加入到函數序列
if(fn && typeof fn == 'function' ){
jQuery.readyList.push(fn);
}
//文檔加載完成,執行函數序列。
if(jQuery.isReady){
for(var i = 0;i < jQuery.readyList.length ;i++){
fn = jQuery.readyList[i];
jQuery.callback(fn);
}
return jQuery;
}
},
//回調
callback : function(fn){
fn.call(document,jQuery);
}
});
//模擬實現jQuery的html方法
jQuery.fn.extend({
html : function(html){
if(html && typeof html == 'string'){
this.obj.innerHTML = html;
return this;
}
return this.obj.innerHTML;
}
});
//導出對象
window.$ = window.jQuery = jQuery;
//判斷加載是否完成
var top = false;
try {
top = window.frameElement == null && document.documentElement;
} catch(e) {}
if ( top && top.doScroll ) {
(function doScrollCheck() {
try {
top.doScroll("left");
jQuery.isReady = true;
jQuery.ready();
} catch(e) {
setTimeout( doScrollCheck, 50 );
}
})();
}
}(window));

 

 

<html><head><script src="my-jquery-1.0.js" type="text/javascript"></script><script type="text/javascript"> $.extend({ testExtend:function(){ alert('extend success'); } }); $.ready(function(){ alert($("test").html()); $.testExtend(); }); $.ready(function(){ $("test").html("modify success"); }); $.ready(function(){ alert($("test").html()); });</script></head><body> <div id="test">jquery src</div></body></html>

相關文章
相關標籤/搜索