javascript // js源碼在構造函數創建完就自動生成了 function Aaa(){}; Aaa.prototype.constructor = Aaa; var a = new Aaa(); alert(a.constructor); // function Aaa(){}; Aaa. ...
//添加實例屬性和方法
jQuery.fn = jQuery.prototype = {
// 版本,使用方式:$().jquery彈出當前引入的jquery的版本
jquery: core_version,
// 修正指向問題(後有詳解)
constructor: jQuery,
// 初始化和參數管理
init: function( selector, context, rootjQuery ) {
var match, elem;
// 寫錯之後的處理,如果寫成: $(""), $(null), $(undefined), $(false),直接返回
if ( !selector ) {
return this;
}
// 對字元串進行處理
if ( typeof selector === "string" ) {
// 如果是這種$('<li>')或$('<li>1</li><li>2</li>')
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// match = [ null, '<li>', null ];或者 match = [ null, '<li>1</li><li>2</li>', null ];
match = [ null, selector, null ];
//如果是$('#div1') $('.box') $('div') $('#div1 div.box')
} else {
//$('.box') $('div') $('#div1 div.box') match = null;
//$('#div1') match = ['#div1',null,'div1'];
//$('<li>hello') match = ['<li>hello','<li>',null];
match = rquickExpr.exec( selector ); //exec()後面詳解
}
// $('<li>') $('#div1') //$('#div1')的上下文為空,即context為false
if ( match && (match[1] || !context) ) {
if ( match[1] ) {
// 如果是$('<li>',document)填寫了第二個對象,並且第二個對象是原生,則直接返回該對象;$('<li>',$(document))如果返回的第二個對象是jQuery,則將它轉換成原生的對象
context = context instanceof jQuery ? context[0] : context;
// 1、jQuery.parseHTML()函數用於將HTML字元串解析為對應的DOM節點數組;使用一個HTML字元串創建一個數組的DOM節點
jQuery.merge( this, jQuery.parseHTML(
match[1], //需要解析並轉成DOM節點數組的HTML字元串
//指定在哪個Document中創建元素,預設為當前文檔的document,可能是iframe
context && context.nodeType ? context.ownerDocument || context : document,
//true,Boolean類型指定傳入的HTML字元串中是否包含腳本,預設為false
true
) );
// 1、rsingleTag.test( match[1] )匹配單標簽,只能匹配<li>或<li></li>,其他都不行
// 2、jQuery.isPlainObject( context )函數用於判斷指定參數是否是一個純粹的對象。{ } 或new Object()或{ name: "CodePlayer"}
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
// jQuery.isFunction用於判斷參數是否是一個函數
if ( jQuery.isFunction( this[ match ] ) ) {
//如果是函數就直接調用該函數,示例:$('<li></li>',{title : 'hi',html : 'abcd',css : {background:'red'}}).appendTo( 'ul' );其中html : 'abcd'就相當於this.html('abcd')
this[ match ]( context[ match ] );
} else {
//如果不是函數就直接添加屬性
this.attr( match, context[ match ] );
}
}
}
return this;
// $('#div1')選擇元素
} else {
elem = document.getElementById( match[2] );
if ( elem && elem.parentNode ) {
// Inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
} else {
return this.constructor( context ).find( selector );
}
//對DOM元素進行處理,$(this),$(document)。
//nodeType屬性返回以數字值返回指定節點的節點類型。如果是元素節點,返回1;如果是屬性節點,返回2
} else if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
// 對函數進行處理
} else if ( jQuery.isFunction( selector ) ) {
// 如果是函數$(function(){}),返回$(document).ready(function(){});
return rootjQuery.ready( selector );
}
// 對空對象或空數組進行處理
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
// jQuery.makeArray()函數用於將一個類數組對象轉換為真正的數組對象(詳解)
return jQuery.makeArray( selector, this );
},
// selector 存儲選擇字元串;
selector: "",
// length this對象的長度
length: 0,
// toArray 專數組
toArray: function() {
return core_slice.call( this );
},
// get 轉原生合集
get: function( num ) {
return num == null ?
// Return a 'clean' array
this.toArray() :
// Return just the object
( num < 0 ? this[ this.length + num ] : this[ num ] );
},
// pushStack JQ對象的入棧(先進後出)
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;
ret.context = this.context;
// Return the newly-formed element set
return ret;
},
// each 遍歷集合
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
// DOM載入介面
ready: function( fn ) {
jQuery.ready.promise().done( fn );
return this;
},
// 集合的截取
slice: function() {
return this.pushStack( core_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] ] : [] );
},
// 返回新集合
map: function( callback ) {
return this.pushStack( jQuery.map(this, function( elem, i ) {
return callback.call( elem, i, elem );
}));
},
// 返回集合前一個狀態
end: function() {
return this.prevObject || this.constructor(null);
},
// push、sort、splice內部使用
push: core_push,
sort: [].sort,
splice: [].splice
};
部分詳解
1、constructor: jQuery
示例:
// js源碼在構造函數創建完就自動生成了
function Aaa(){};
Aaa.prototype.constructor = Aaa;
var a = new Aaa();
alert(a.constructor); // function Aaa(){};
Aaa.prototype.constructor = Array;
alert(a.constructor); // function Array() { [native code] }
Aaa.prototype = {
constructor : Aaa,
name : 'hello',
age : 30
};
var a1 = new Aaa();
alert(a1.constructor); // function Aaa(){};
這個constructor屬性非常容易被不小心修改掉,所以jquery需要修正指向
2、match = rquickExpr.exec( selector )
示例:
var rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
var selector = "#div1";
var match = rquickExpr.exec( selector );
console.log(match); //match = ['#div1',null,'div1'];
exec() 方法就是用來檢索字元串中正則表達式的匹配,如果匹配到了那麼就返回一個存放有結果的數組,如果沒有匹配到就返回一個null;
match是數組,第0個元素是與正則表達式相匹配的文本,第1個元素是與正則表達式的第1個子表達式相匹配的文本(如果有的話),第2個元素是第2個子表達式相匹配的文本(如果有的話),第3個元素是第3個子表達式相匹配的文本(如果有的話),這裡就是元素的ID,不包含#。
3、jQuery.makeArray()
var aDiv = document.getElementsByTagName('div');
aDiv並不是一個真正的數組,可以用$.makeArray(aDiv)轉成一個數組 ;$.makeArray(aDiv,{length:0})將它轉成一個對象
$([]) $({})