天天看點

jQuery技術内幕:深入解析jQuery架構設計與實作原理. 2.8 靜态屬性和方法

<b>2.8 靜态屬性和方法</b>

在構造jquery對象子產品中還定義了一些重要的靜态屬性和方法,它們是其他子產品實作的基礎。其整體源碼結構如代碼清單2-3所示。

代碼清單2-3 靜态屬性和方法

388 jquery.extend({

389    

noconflict: function( deep ) {},

402    

isready: false,

406    

readywait: 1,

409    

holdready: function( hold ) {},

418    

ready: function( wait ) {},

444    

bindready: function() {},

492    

isfunction: function( obj ) {},

496    

isarray: array.isarray || function( obj ) {},

501    

iswindow: function( obj ) {},

505    

isnumeric: function( obj ) {},

509    

type: function( obj ) {},

515    

isplainobject: function( obj ) {},

544    

isemptyobject: function( obj ) {},

551    

error: function( msg ) {},

555    

parsejson: function( data ) {},

581    

parsexml: function( data ) {},

601    

noop: function() {},

606    

globaleval: function( data ) {},

619    

camelcase: function( string ) {},

623    

nodename: function( elem, name ) {},

628    

each: function( object, callback, args ) {},

669    

trim: trim ? function( text ) {} : function( text ) {},

684    

makearray: function( array, results ) {},

702    

inarray: function( elem, array, i ) {},

724    

merge: function( first, second ) {},

744    

grep: function( elems, callback, inv ) {},

761    

map: function( elems, callback, arg ) {},

794    

guid: 1,

798    

proxy: function( fn, context ) {},

825    

access: function( elems, key, value, exec, fn, pass ) {},

852    

now: function() {},

858    

uamatch: function( ua ) {},

870    

sub: function() {},

891    

browser: {}

892 });

jquery.isready、jquery.readywait、jquery.holdready()、jquery.ready()、jquery.bindready()用于支援ready事件,将在9.11節對它們進行介紹和分析;jquery.each()和jquery.map()已經在2.7.3節和2.7.4節介紹和分析過了;jquery.sub()在jquery源碼中沒有用到,并且不推薦使用,這裡不做分析;下面對其他的靜态屬性和方法逐一介紹和分析。

2.8.1 jquery.noconflict(

[removeall] )

方法jquery.noconflict( [removeall] )用于釋放jquery對全局變量$的控制權,可選的參數removeall訓示是否釋放對全局變量jquery的控制權。$僅僅是jquery的别名,所有的功能沒有$也能使用。

很多javascript庫使用美元符$作為函數名或變量名,在使用jquery的同時,如果需要使用另一個javascript庫,可以調用$.noconflict()傳回$給其他庫。如果有必要(例如,在一個頁面中使用多個版本的jquery庫,但很少有這樣的必要),也可以釋放全局變量jquery的控制權,隻需要給這個方法傳入參數true即可。

方法jquery.noconflict( [removeall] )相關代碼如下所示:

30     // map over jquery in case

of overwrite

31     _jquery = window.jquery,

  32

33     // map over the $ in case

34     _$ = window.$,

 388 jquery.extend({

 389    

noconflict: function( deep ) {

 390        

if ( window.$ === jquery ) {

 391            

window.$ = _$;

 392        

}

 393

 394        

if ( deep &amp;&amp; window.jquery === jquery ) {

 395            

window.jquery = _jquery;

 396        

 397

 398        

return jquery;

 399    

},

9245 // expose jquery to

the global object

9246 window.jquery =

window.$ = jquery;

第30~34行:jquery初始化時,把可能存在的window.jquery和window.$備份到局部變量_jquery和_$。

第390~392行:如果window.$ === jquery,則設定window.$為初始化時備份的_$。也就是說,隻有在目前jquery庫持有全局變量$的情況下,才會釋放$的控制權給前一個javascript庫。

從jquery 1.6開始增加了對window.$ === jquery的檢測。如果不檢測,則每次調用jquery.noconflict()時都會釋放$給前一個javascript庫,當頁面中有兩個以上定義了$的 javascript庫時,對$的管理将會變得混亂。

第394~396行:如果參數deep為true,并且window.jquery === jquery,則設定window.jquery為初始化時備份的_jquery。也就是說,如果參數deep為true,隻有在目前jquery庫持有全局變量jquery的情況下,才會釋放jquery的控制權給前一個javascript庫。

從jquery 1.6開始增加了對window.$ === jquery的檢測。如果不檢測,則每次調用jquery.noconflict( true )時都會釋放jquery給前一個javascript庫,當頁面中有兩個以上定義了jquery的javascript庫時,對jquery的管理将會變得混亂。

2.8.2 類型檢測:jquery.isfunction(

obj )、jquery.isarray( obj )、jquery

   .iswindow( obj )、jquery.isnumeric( value )、jquery.type( obj )、

   jquery.isplainobject( object )、jquery.isemptyobject(

object )

1.?jquery.isfunction( obj )、jquery.isarray(

obj )

方法jquery.isfunction( obj )用于判斷傳入的參數是否是函數;方法jquery.isarray(

obj )用于判斷傳入的參數是否是數組。這兩個方法的實作依賴于方法jquery.type( obj ),通過判斷 jquery.type( obj )傳回值是否是“function”和“array”來實作。相關代碼如下所示:

489    

// see test/unit/core.js for details concerning isfunction.

490    

// since version 1.3, dom methods and functions like alert

491    

// aren't supported. they return false on ie (#2968).

isfunction: function( obj ) {

493       

return jquery.type(obj) === "function";

494    

495

isarray: array.isarray || function( obj ) {

497       

return jquery.type(obj) === "array";

498    

499

2.?jquery.type( obj )

方法jquery.type( obj )用于判斷參數的内建javascript類型。如果參數是undefined或null,傳回“undefined”或“null”;如果參數是javascript内部對象,則傳回對應的字元串名稱;其他情況一律傳回“object”。相關代碼如下所示:

type: function( obj ) {

510        

return obj == null ?

511            string( obj ) :

512            class2type[ tostring.call(obj) ] ||

"object";

513    

第510~511行:如果參數obj是undefined或null,通過string( obj )轉換為對應的原始字元串“undefined”或“null”。

第512行:先借用object的原型方法tostring()擷取obj的字元串表示,傳回值的形式為[object class],其中的class是内部對象類,例如,object.prototype.tostring.call( true )會傳回

[object boolean];然後從對象class2type中取出[object

class]對應的小寫字元串并傳回;如果未取到則一律傳回“object”。原型方法tostring()和對象class2type的定義和初始化源碼如下所示:

 87    tostring = object.prototype.tostring,

 94    // [[class]] -&gt; type pairs

 95    class2type = {};

894 // ppulate the

class2type map

895 jquery.each("boolean

number string function array date regexp object".split(" "),

function(i, name) {

896    class2type[ "[object " + name +

"]" ] = name.tolowercase();

897 });

對象class2type初始化後的結構為:

{

"[object array]": "array"

"[object boolean]": "boolean"

"[object date]": "date"

"[object function]": "function"

"[object number]": "number"

   "[object object]":

"object"

"[object regexp]": "regexp"

"[object string]": "string"

3.?jquery.iswindow( obj )

方法jquery.iswindow( obj )用于判斷傳入的參數是否是window對象,通過檢測是否存在特征屬性setinterval來實作,相關代碼如下所示:

500    

// a crude way of determining if an object is a window

iswindow: function( obj ) {

502       

return obj &amp;&amp; typeof obj === "object" &amp;&amp;

"setinterval" in obj;

503    

在本書寫作時釋出的jquery 1.7.2中,該方法改為檢測特征屬性window,該屬性是對視窗自身的引用,相關代碼如下所示:

// 1.7.2

return obj != null &amp;&amp; obj == obj.window;

4.?jquery.isnumeric( value )

方法jquery.isnumeric( value )用于判斷傳入的參數是否是數字,或者看起來是否像數字,相關代碼如下所示:

isnumeric: function( obj ) {

506       

return !isnan( parsefloat(obj) ) &amp;&amp; isfinite( obj );

507    

第506行:先執行parsefloat( obj )嘗試把參數obj解析為數字,然後用isnan()判斷解析結果是否是合法數字,并用isfinite()判斷參數obj是否是有限的。如果parsefloat( obj )的解析結果是合法數字,并且參數obj是有限數字,則傳回true;否則傳回false。

方法parsefloat( string )用于對字元串參數進行解析,并傳回字元串中的第一個數字。在解析過程中,如果遇到了不是有效數字的字元,解析就會停止并傳回解析結果;如果字元串沒有以一個有效的數字開頭,則傳回nan;如果傳入的參數是對象,則自動調用該對象的方法tostring(),得到該對象的字元串表示,然後再執行解析過程。

方法isnan( x )用于判斷參數是否為非數字值,常用于檢測方法parsefloat()和parseint()的解析結果。

方法isfinite( number )用于判斷一個數字是否是有限的。

5.?jquery.isplainobject( object )

方法jquery.isplainobject( object )用于判斷傳入的參數是否是“純粹”的對象,即是否是用對象直接量{}或new object()建立的對象。相關代碼如下所示:

isplainobject: function( obj ) {

516        

// must be an object.

517        

// because of ie, we also have to check the presence of the constructor

property.

518        

// make sure that dom nodes and window objects don't pass through, as

well

519        

if ( !obj || jquery.type(obj) !== "object" || obj.nodetype ||

jquery.iswindow( obj ) ) {

520             return false;

521        

522

523        

try {

524             // not own constructor property

must be object

525             if ( obj.constructor &amp;&amp;

526                 !hasown.call(obj,

"constructor") &amp;&amp;

527                

!hasown.call(obj.constructor.prototype, "isprototypeof") ) {

528                 return false;

529             }

530        

} catch ( e ) {

531             // ie8,9 will throw exceptions on

certain host objects #9897

532             return false;

533        

534

535        

// own properties are enumerated firstly, so to speed up,

536        

// if last one is own, then all properties are own.

537

538        

var key;

539        

for ( key in obj ) {}

540

541        

return key === undefined || hasown.call( obj, key );

542    

第519~521行:如果參數obj滿足以下條件之一,則傳回false:

參數obj可以轉換為false。

object.prototype.tostring.call( obj )傳回的不是[object

object]。

參數obj是dom元素。

參數obj是window對象。

如果參數obj不滿足以上所有條件,則至少可以确定參數obj是對象。

第523~533行:檢查對象obj是否由構造函數object()建立。如果對象obj滿足以下所有條件,則認為不是由構造函數object()建立,而是由自定義構造函數建立,傳回false:

對象obj含有屬性constructor。由構造函數建立的對象都有一個constructor屬性,預設引用了該對象的構造函數。如果對象obj沒有屬性constructor,則說明該對象必然是通過對象字面量{}建立的。

對象obj的屬性constructor是非繼承屬性。預設情況下,屬性constructor繼承自構造函數的原型對象。如果屬性constructor是非繼承屬性,說明該屬性已經在自定義構造函數中被覆寫。

對象obj的原型對象中沒有屬性isprototypeof。屬性isprototypeof是object原型對象的特有屬性,如果對象obj的原型對象中沒有,說明不是由構造函數object()建立,而是由自定義構造函數建立。

執行以上檢測時抛出了異常。在ie 8/9中,在某些浏覽器對象上執行以上檢測時會抛出異常,也應該傳回false。

函數hasown()指向object.prototype.hasownproperty( property ),用于檢查對象是否含有執行名稱的非繼承屬性。

第539~541行:檢查對象obj的屬性是否都是非繼承屬性。如果沒有屬性,或者所有屬性都是非繼承屬性,則傳回true。如果含有繼承屬性,則傳回false。

第539行:執行for-in循環時,javascript會先枚舉非繼承屬性,再枚舉從原型對象繼承的屬性。

第541行:如果對象obj的最後一個屬性是非繼承屬性,則認為所有屬性都是非繼承屬性,傳回true;如果最後一個屬性是繼承屬性,即含有繼承屬性,則傳回false。

6.?jquery.isemptyobject( object )

方法jquery.isemptyobject( object )用于檢測對象是否是空的(即不包含屬性)。例如:

jquery.isemptyobject( {} )                           // true

jquery.isemptyobject( new object() )               // true

jquery.isemptyobject( { foo:

"bar" } )               // false

方法jquery.isemptyobject( object )的相關代碼如下所示:

isemptyobject: function( obj ) {

545        

for ( var name in obj ) {

546             return false;

547        

548        

return true;

549    

第545~548行:for-in循環會同時枚舉非繼承屬性和從原型對象繼承的屬性,如果有,則立即傳回false,否則預設傳回true。

2.8.3 解析json和xml:jquery.parsejson(

data )、jquery.parsexml( data )

1.?jquery.parsejson( data )

方法jquery.parsejson( data )接受一個格式良好的json字元串,傳回解析後的javascript對象。如果傳入殘缺的json字元串可能導緻程式抛出異常;如果不傳入參數,或者傳入空字元串、null、undefined,則傳回null。

如果浏覽器提供了原生方法json.parse(),則使用該方法解析json字元串;否則使用

( new function( "return"+ data )

)()解析json字元串。

方法jquery.parsejson( data )的相關代碼如下所示:

555     

parsejson: function( data ) {

556        

if ( typeof data !== "string" || !data ) {

557             return null;

558        

559

560        

// make sure leading/trailing whitespace is removed (ie can't handle it)

561        

data = jquery.trim( data );

562

563        

// attempt to parse using the native json parser first

564        

if ( window.json &amp;&amp; window.json.parse ) {

565             return window.json.parse( data );

566        

567

568        

// make sure the incoming data is actual json

569        

// logic borrowed from http:// json.org/json2.js

570        

if ( rvalidchars.test( data.replace( rvalidescape, "@" )

571             .replace( rvalidtokens,

"]" )

572             .replace( rvalidbraces,

"")) ) {

573

574             return ( new function(

"return " + data ) )();

575

576        

577        

jquery.error( "invalid json: " + data );

578     

第556~561行:對于非法參數一律傳回null。如果參數data不是字元串,或者可以轉換為false,則傳回null。

第561行:移除開頭和末尾的空白符。在ie 6/7中,如果不移除就不能正确的解析,例如:

typeof ( new function( 'return ' + '\n{}' )

)();

// 傳回"undefined"

第564~566行:嘗試使用原生方法json.parse()解析json字元串,并傳回。

json對象含有兩個方法:json.parse()和json.stringify(),用于json字元串和javascript對象之間的互相轉換。下面是它們的文法和使用示例。

json.parse()解析json字元串為 json對象,其文法如下:

json.parse(text[, reviver])

// text 待解析為 json 對象的字元串

// reviver 可選。在傳回解析結果前,對解析結果中的屬性值進行修改

json.parse()的使用示例如下所示:

json.parse( '{ "abc": 123 }' );

// {"abc": 123 }

json.parse( '{ "abc": 123 }',

function( key, value ){

if( key === '' ) return value;

return value * 2;

} );

// {"abc": 246 }

json.stringify()轉換json對象為json字元串,其文法如下:

json.stringify( value[, replacer [, space]]

)

// value 待轉換為 json 字元串的對象

// replacer 可選。如果 replacer 是函數,轉換前先執行

replacer 改變屬性值,如果函數 replacer 傳回 undefined,則對應的屬性不會出現在結果中;如果 replacer 是數組,指定最終字元串中包含的屬性集合,不在數組 replacer 中的屬性不會出現在結果中

// space 增加轉換後的 json 字元串的可讀性

json.stringify()的使用示例如下所示:

json.stringify( { a: 1, b: 2 } );

// '{"a":1,"b":2}'

json.stringify( { a: 1, b: 2 }, function(

key, value ){

if( key === 'a' ) return value * 10;

if( key === 'b' ) return undefined;

return value;

// '{"a":10}'

json.stringify( { a: 1, b: 2 }, ['b'] );

// '{"b":2}'

json.stringify( { a: 1, b: 2 }, null, 4 );

// '{\n   

"a": 1,\n   

"b": 2\n}'

json對象、json.parse()、json.stringify()在ecmascript 5中被标準化,ie 8以下的浏覽器不支援。關于json規範和浏覽器實作的更多資訊請通路以下位址:

http://json.org/json-zh.html

http://www.ecma-international.org/publications/standards/ecma-262.htm(ecmascript 5第15.12節)

https://developer.mozilla.org/en/javascript/reference/global_objects/json

下面回到對方法jquery.parsejson()的分析中來。

第570~576行:在不支援json.parse()的浏覽器中,先檢查字元串是否合法,如何合法,才會執行( new function("return"+ data) )()并傳回執行結果。檢查字元串是否合法的正則和邏輯來自開源json解析庫json2.js(https://github.com/douglascrockford/json-js),檢測過程分為4步,用到了4個正規表達式:rvalidchars、rvalidescape、rvalidtokens、rvalidbraces,相關代碼如下:

 53    

// json regexp

 54     rvalidchars = /^[\],:{}\s]*$/,

 55    

rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fa-f]{4})/g,

 56    

rvalidtokens =

/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[ee][+\-]?\d+)?/g,

 57    

rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

第54~57行:正則rvalidescape用于比對轉義字元;正則rvalidtokens用于比對有效值(字元串、true、false、null、數值);正則rvalidbraces用于比對正确的左方括号“[”;正則rvalidchars用于檢查字元串是否隻含有指定的字元(“]”、“,”、“:”、“{”、“}”、“\s”)。

第570~572行:先利用正則rvalidescape把轉義字元替換為“@”,為進行下一步替換做準備;再利用正則rvalidtokens把字元串、true、false、null、數值替換為“]”;然後利用rvalidbraces删除正确的左方括号;最後檢查剩餘字元是否隻包含“]”、“,”、“:”、“{”、“}”、“\s”,如果隻包含這些字元,那麼認為json字元串是合法的。

第574行:通過構造函數function()建立函數對象,然後執行。構造函數function()的文法如下:

new function( arguments_names..., body)

// 參見arguments_names...:任意多個字元串參數,每個字元串命名一個或多個要建立的 function 對象的參數

// 參見body:一個字元串,指定函數的主體,可以含有任意多條 javascript 語句,這些語句之間用分号隔開,可以給該構造函數引用前面的參數設定的任何參數名

// 傳回新建立的 function 對象。調用該函數,将執行

body 指定的 javascript 代碼

第577行:如果浏覽器不支援json.parse(),并且json字元串不合法,則在最後抛出一個異常。

2.?jquery.parsexml( data )

方法jquery.parsexml( data )接受一個格式良好的xml字元串,傳回解析後的xml文檔。

方法jquery.parsexml()使用浏覽器原生的xml解析函數實作。在ie 9+和其他浏覽器中,會使用domparser對象解析;在ie 9以下的浏覽器中,則使用activexobject對象解析。相關代碼如下所示:

580    

// cross-browser xml parsing

parsexml: function( data ) {

582        

var xml, tmp;

583        

584             if ( window.domparser ) { //

sandard

585                 tmp = new domparser();

586                 xml = tmp.parsefromstring( data

, "text/xml" );

587             } else { //ie

588                 xml = new activexobject(

"microsoft.xmldom" );

589                 xml.async = "false";

590                 xml.loadxml( data );

591         

   }

592        

} catch( e ) {

593             xml = undefined;

594        

595        

if ( !xml || !xml.documentelement || xml.getelementsbytagname(

"parsererror" ).length ) {

596             jquery.error( "invalid xml:

" + data );

597        

598        

return xml;

599    

第584~586行:嘗試用标準解析器domparser解析。domparser在html5中标準化,可以将xml或html字元串解析為一個dom文檔。解析時,首先要建立一個domparser對象,然後使用它的方法parsefromstring()來解析xml或html字元串。方法parsefromstring()的文法如下:

domparser.parsefromstring( domstring str,

supportedtype type )

// 參數str:待解析的 xml 或 html 字元串

// 參數type:支援的類型有"text/html"、"text/xml"、"application/xml"、"application/xhtml+xml"、"image/svg+xml"

// 傳回一個解析後的新建立的文檔對象

在ie以外的浏覽器中,如果解析失敗,方法parsefromstring()不會抛出任何異常,隻會傳回一個包含了錯誤資訊的文檔對象,如下所示:

&lt;parsererror xmlns="http:// www.mozilla.org/newlayout/xml/parsererror.xml"&gt;

(error description)

&lt;sourcetext&gt;(a snippet of the source xml)&lt;/sourcetext&gt;

&lt;/parsererror&gt;

是以,在第595行需要檢查解析後的文檔中是否包含&lt;parsererror&gt;節點,如果包含則表示解析失敗,抛出一個更易讀的異常。

在ie 9+中,如果解析失敗,則會抛出異常。如果抛出異常,在catch塊中設定xml為undefined,然後抛出一個更易讀的異常。

可以運作下面的測試代碼來驗證上述内容:

new

domparser().parsefromstring("&lt;a&gt;hello" , "text/xml")

在chrome中傳回一個包含了錯誤資訊的文檔對象:

&lt;a&gt;

&lt;parsererror style="display: block; white-space: pre; border:

2px solid #c77;

padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color:

black"&gt;

&lt;h3&gt;this page contains the following errors:&lt;/h3&gt;

&lt;div style="font-family:monospace;font-size:12px"&gt;

error on line 1 at column 9: extra content at the end of the document

&lt;/div&gt;

&lt;h3&gt;below is a rendering of the page up to the first

error.&lt;/h3&gt;

&lt;/parsererror&gt;hello

&lt;/a&gt;

在ie 9中則抛出異常:

"dom exception: syntax_err (12)"

xml5602: 輸入意外結束。

, 行1 字元9

下面回到對方法jquery.parsexml()源碼的分析中來。

第588~594行:ie 9以下的浏覽器不支援domparser,需要使用微軟的xml解析器microsoft.xmldom解析。解析步驟依次為:建立一個空的xml文檔對象,設該文檔對象為同步加載,調用方法loadxml()解析xml字元串。

如果解析成功,方法loadxml()會傳回true,解析結果存放在建立的xml文檔對象中;如果解析失敗,方法loadxml()會傳回false(不會抛出異常),并設定文檔根節點documentelement為null。

第595~597行:如果解析失敗,則抛出一個更易讀的異常。如果滿足以下條件之一,則認為解析失敗:

在ie 9+中,通過标準xml解析器domparser解析失敗,此時!xml為true。

在ie 9以下的浏覽器中,通過微軟的xml解析器microsoft.xmldom解析失敗,此時!xml.documentelement為true。

在其他浏覽器中,通過标準xml解析器domparser解析失敗,此時xml.getelementsbytagname("parsererror").length可以轉換為true。

第598行:如果解析成功,則傳回解析結果。

下面是一些擴充閱讀:

xml文檔屬性和方法:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms763798(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/ms757828(v=vs.85).aspx

解析xml文檔:

http://www.w3schools.com/xml/xml_parser.asp

html5規範中的xml序列化:

http://html5.org/specs/dom-parsing.html#xmlserializer      

2.8.4 jquery.globaleval(

code )

方法jquery.globaleval( code )用于在全局作用域中執行javascript代碼。很多時候我們希望javascript代碼是在全局作用域中執行,例如,當動态加載并執行javascript代碼時。

在ie中,可以調用方法execscript()讓javascript代碼在全局作用域中執行;在其他浏覽器中,則需要在一個自調用匿名函數中調用eval()執行javascript代碼,自調用匿名函數確定了執行環境是全局作用域。相關代碼如下所示:

603    

// evaluates a script in a global context

604    

// workarounds based on findings by jim driscoll

605    

//

http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-

global-context

globaleval: function( data ) {

607        

if ( data &amp;&amp; rnotwhite.test( data ) ) {

608             // we use execscript on internet

explorer

609             // we use an anonymous function so

that context is window

610             // rather than jquery in firefox

611             ( window.execscript || function(

data ) {

612               window[ "eval" ].call(

window, data );

613             } )( data );

614        

615    

方法execscript()在全局作用域中按照指定的腳本語言執行腳本代碼,預設語言是jscript,沒有傳回值。該方法的文法如下:

execscript( code, language )

// 參數code:待執行的腳本代碼

// 參數language:腳本語言,可選值有javascript、javascript1.1、javascript1.2、javascript1.3、

jscript、vbs、vbscript,預設是 jscript

chrome的早期版本曾支援方法execscript(),現已不支援。

方法eval()在調用它的作用域中計算或執行javascript代碼。如果javascript代碼是一條表達式,則計算并傳回計算結果;如果含有一條或多條javascript語句,則執行這些語句,如果最後一條語句有傳回值,則傳回這個值,否則傳回undefined。該方法的文法如下:

eval( code )

// 參數code:待執行的

javascript 表達式或語句

第611~613行:如果支援方法execscript(),則執行execscript( data );否則建立一個自調用匿名函數,在函數内部執行“window[ "eval" ].call( window, data );”,讀者可以通路源碼注釋第605行的網頁位址檢視如此書寫的原因。

2.8.5 jquery.camelcase(

string )

方法jquery.camelcase( string )轉換連字元式的字元串為駝峰式,用于css子產品和資料緩存子產品。例如:

jquery.camelcase( 'background-color' );

// "backgroundcolor"

方法jquery.camelcase( string )的相關代碼如下所示:

 65    

// matches dashed string for camelizing

 66    

rdashalpha = /-([a-z]|[0-9])/ig,

 67    

rmsprefix = /^-ms-/,

 68

 69    

// used by jquery.camelcase as callback to replace()

 70    

fcamelcase = function( all, letter ) {

 71        

return ( letter + "" ).touppercase();

 72    

617    

// convert dashed to camelcase; used by the css and data modules

618    

// microsoft forgot to hump their vendor prefix (#9572)

camelcase: function( string ) {

620        

return string.replace( rmsprefix, "ms-" ).replace( rdashalpha,

fcamelcase );

621    

第66行:正則rdashalpha用于比對字元串中連字元“-”和其後的第一個字母或數字。如果連字元“-”後是字母,則比對部分會被替換為對應的大寫字母;如果連字元“-”後是數字,則會删掉連字元“-”,保留數字。

第67行:正則rmsprefix用于比對字元串中字首“-ms-”,比對部分會被替換為“ms-”。這麼做是因為在ie中,連字元式的樣式名字首“-ms-”對應小寫的“ms”,而不是駝峰式的“ms”。例如,“-ms-transform”對應“mstransform”而不是“mstransform”。在ie以外的浏覽器中,連字元式的樣式名則可以正确地轉換為駝峰式,例如,“-moz-transform”對應“moztransform”。

第70~72行:函數fcamelcase()負責把連字元後的字母轉換為大寫并傳回。

第619~621行:在方法jquery.camelcase()中,先用正則rmsprefix比對字首“-ms-”,如果有則修正為“ms-”;然後用正則rdashalpha比對連字元“-”和其後的第一個字母或數字,并用字元串方法replace()和函數fcamelcase()把比對部分替換為對應的大寫字母或數字。

2.8.6 jquery.nodename(

elem, name )

方法jquery.nodename( elem, name )用于檢查dom元素的節點名稱(即屬性nodename)與指定的值是否相等,檢查時忽略大小寫。

dom元素的屬性nodename傳回該元素的節點名稱;對于html文檔,始終傳回其大寫形式;對于xml文檔,因為xml文檔區分大小寫,是以傳回值與源代碼中的形式一緻。在方法jquery.nodename( elem, name )中會把屬性nodename和參數name轉換為大寫形式後再做比較,即忽略大小寫。相關代碼如下所示:

nodename: function( elem, name ) {

624       

return elem.nodename &amp;&amp; elem.nodename.touppercase() ===

name.toupper

case();

625    

第624行:把屬性elem.nodename和參數name都轉換為大寫再做比較。在執行elem.nodename.touppercase()前先檢查elem.nodename是否存在,可以有效地避免參數elem不是dom元素,或者參數elem沒有屬性nodename導緻的錯誤。

2.8.7 jquery.trim( str )

方法jquery.trim( str )用于移除字元串開頭和結尾的空白符。如果傳入的參數是null或undefined,則傳回空字元串;如果傳入的參數是對象,則先擷取對象的字元串表示,然後移除開頭和結尾的空白符,并傳回。相關代碼如下所示:

 43    

// check if a string has a non-whitespace character in it

 44    

rnotwhite = /\s/,

 45

 46    

// used for trimming whitespace

 47    

trimleft = /^\s+/,

 48    

trimright = /\s+$/,

 91    

trim = string.prototype.trim,

910 // ie doesn't match

non-breaking spaces with \s

911 if ( rnotwhite.test(

"\xa0" ) ) {

912    

trimleft = /^[\s\xa0]+/;

913    

trimright = /[\s\xa0]+$/;

914 }

668    

// use native string.trim function wherever possible

trim: trim ?

670        

function( text ) {

671             return text == null ?

672                 "" :

673                 trim.call( text );

674        

} :

675

676        

// otherwise use our own trimming functionality

677        

678             return text == null ?

679                 "" :

680                 text.tostring().replace(

trimleft, "" ).replace( trimright, "" );

681        

第47~48行:正則trimleft用于比對字元串開頭的空白符;trimright用于比對字元串結尾的空白符。

第911~914行:在ie 9以下的浏覽器中,\s不比對不間斷空格\xa0,需要為正則trimleft和trimright加上“\xa0”。

第669~681行:如果浏覽器支援string.prototype.trim()則“借雞生蛋”,string.prototype.

trim()是ecmascript 5新增的string原型方法;如果不支援,則先調用方法tostring()得到參數text的字元串表示,然後調用方法replace()把正則trimleft和trimright比對到的空白符替換為空字元串。如果參數是null或undefined,則傳回空字元串。

2.8.8 數組操作方法:jquery.makearray(

obj )、jquery.inarray( value,

   array [, fromindex] )、jquery.merge( first, second )、jquery.

   grep( array, function(elementofarray, indexinarray) [, invert] )

1.?jquery.makearray( obj )

方法jquery.makearray( obj )可以将一個類數組對象轉換為真正的數組。

在jquery内部,還可以為方法jquery.makearray()傳入第二個參數,這樣,第一個參數中的元素将被合并入第二個參數,最後會傳回第二個參數,此時傳回值的類型不一定是真正的數組。

方法jquery.makearray( obj )的源碼如下:

 89    

push = array.prototype.push,

683    

// results is for internal usage only

makearray: function( array, results ) {

685       

var ret = results || [];

686

687       

if ( array != null ) {

688            // the window, strings (and

functions) also have 'length'

689            // theaked logic slightly to handle

blackberry 4.7 regexp issues #6930

690            var type = jquery.type( array );

691

692            if ( array.length == null

                     || type ===

"string"

"function"

"regexp"

                     || jquery.iswindow( array ) )

693                push.call( ret, array );

694            } else {

695               jquery.merge( ret, array );

696            }

697       

698

699        

return ret;

700    

第684行:定義方法jquery.makearray( array, results ),它接受2個參數:

參數array:待轉換對象,可以是任何類型。

參數results:僅在jquery内部使用。如果傳入參數results,則在該參數上添加元素。

第685行:定義傳回值ret。如果傳入了參數results則把該參數作為傳回值,否則建立一個空數組作為傳回值。

第687行:過濾參數array是null、undefined的情況。

第690~693行:如果參數array滿足以下條件之一,則認為該參數不是數組,也不是類數組對象,調用數組方法push()把該參數插入傳回值ret的末尾:

參數array沒有屬性length。

參數array是字元串,屬性length傳回字元串中的字元個數。

參數array是函數,屬性length傳回函數聲明時的參數個數。

參數array是window對象,屬性length傳回視窗中的架構(frame、iframe)個數。

參數array是正則對象,在blackberry(黑莓)4.7中,正則對象也有length屬性。

注意,第693行插入元素時執行的是push.call( ret,array ),而不是ret.push( array ),這是因為傳回值ret不一定是真正的數組。如果隻傳入參數array,則傳回值ret是真正的數組;如果還傳入了第二個參數result,則傳回值ret的類型取決于該參數的類型。

第694~696行:否則認為參數array是數組或類數組對象,調用方法jquery.merge()把該參數合并到傳回值ret中。

第699行:最後傳回ret。

2.?jquery.inarray( value, array[,

fromindex] )

方法jquery.inarray( value, array[, fromindex] )在數組中查找指定的元素并傳回其下标,未找到則傳回-1。相關代碼如下所示:

inarray: function( elem, array, i ) {

703        

var len;

704

705        

if ( array ) {

706             if ( indexof ) {

707                 return indexof.call( array,

elem, i );

708             }

709

710             len = array.length;

711             i = i ? i &lt; 0 ? math.max( 0,

len + i ) : i : 0;

712

713             for ( ; i &lt; len; i++ ) {

714                 // sip accessing in sparse

arrays

715                 if ( i in array &amp;&amp;

array[ i ] === elem ) {

716                     return i;

717                 }

718             }

719        

720

721        

return -1;

722    

第702行:定義方法jquery.inarray( elem, array, i ),它接受3個參數:

參數elem:要查找的值。

參數array:數組,将周遊這個數組來查找參數value在其中的下标。

參數i:指定開始查找的位置,預設是0即查找整個數組。

第705行:過濾array可以轉換為false的情況。

第706~708行:如果浏覽器支援數組方法indexof(),則調用它并傳回下标。該方法在ecmascript 5中被标準化。

第711行:修正參數i。如果未指定參數i,則初始化為0,表示預設從頭開始周遊;如果i小于0,則加上數組長度len,即從數組末尾開始計算,例如,-1表示最後一個元素,-2表示倒數第二個元素,以此類推。注意,這裡調用了math.max()方法在0和len+i之間取最大值,即如果len+i依然小于0,則把i修正為0,仍然從頭開始周遊。

第713~718行:從指定位置開始周遊數組,查找與指定值elem相等的元素,并傳回其下标。先檢測i in array,如果結果是false,說明數組array的下标是不連續的,也不需要與指定值elem比較;然後檢測array[i]=== elem,如果結果是true,則傳回目前下标。這裡使用等同運算符( === )來避免類型轉換。

第721行:如果沒有找到與指定值相等的元素,則預設傳回-1。從方法jquery.inarray()的命名來看,這個方法應該傳回true或false,而它實際上傳回的卻是下标,是以把方法名改為indexof或許更合适些,但是這個方法從jquery 1.2就一直存在,如果修改則會導緻嚴重的向後相容問題,是以傳回值和方法名都不宜修改。

通常我們會比較jquery.inarray()的傳回值是否大于0,來判斷某個指定的元素是否是數組中的元素,就像下面這樣:

if( jquery.inarray( elem, array ) &gt; 0 ){

   //

elem 是 array 中的元素

上面的寫法比較繁瑣,特别是當if語句檢測的條件是複合布爾表達式時,可讀性會很差;可以用按位非運算符(~)簡化上面的代碼:

if( ~jquery.inarray( elem, array ) ){

按位非運算符(~)會将運算數的所有位取反,相當于改變它的符号并且減1,例如:

~-1 == 0; // true

~0 == -1; // true

~1 == -2; // true

~2 == -3; // true

更進一步,可以結合使用按位非運算符(~)和邏輯非運算符(!)把jquery.inarray()的傳回值轉換為布爾型:

!!~jquery.inarray( elem, array )

// 如果elem 可以比對 array 中的某個元素,則該表達式的值為 true

// 如果elem 比對不到 array 中的元素,則該表達式的值為

false

3.?jquery.merge( first, second )

方法jquery.merge( first, second )用于合并兩個數組的元素到第一個數組中。事實上,第一個參數可以是數組或類數組對象,即必須含有整型(或可以轉換為整型)屬性length;第二個參數則可以是數組、類數組對象或任何含有連續整型屬性的對象。

方法jquery.merge()的合并行為是破壞性的,将第二個數組中的元素添加到第一個數組中後,第一個數組就被改變了。如果希望原來的第一個數組不被改變,可以在調用jquery.merge()之前建立一份第一個數組的副本:

var newarray = $.merge([], oldarray);

方法jquery.merge( first, second )的相關代碼如下所示:

merge: function( first, second ) {

725        

var i = first.length,

726             j = 0;

727

728        

if ( typeof second.length === "number" ) {

729             for ( var l = second.length; j

&lt; l; j++ ) {

730                 first[ i++ ] = second[ j ];

731             }

732

733        

} else {

734             while ( second[j] !== undefined )

735                 first[ i++ ] = second[ j++ ];

736             }

737        

738

739        

first.length = i;

740

741     

   return first;

742    

第724行:定義方法jquery.merge( first, second ),它接受2個參數:

參數first:數組或類數組對象,必須含有整型(或可以轉換為整型)屬性length,第二個數組second中的元素會被合并到該參數中。

參數second:數組、類數組對象或任何含有連續整型屬性的對象,其中的元素會被合并到第一個參數first中。

第725行:初始化變量i為first.length,該變量訓示了插入新元素時的下标。first.length必須是整型或可以轉換為整型,否則後面執行i++時會傳回nan。

第728~731行:如果參數second的屬性length是數值類型,則把該參數當作數組處理,把其中的所有元素都添加到參數first中。

第733~737行:如果參數second沒有屬性length,或者屬性length不是數值類型,則把該參數當作含有連續整型(或可以轉換為整型)屬性的對象,例如,{ 0:'a', 1:'b'},把其中的非undefined元素逐個插入參數first中。

第739行:修正first.length。因為參數first可能不是真正的數組,是以需要手動維護屬性length的值。

第741行:傳回改變後的參數first。

4.?jquery.grep( array, function(

elementofarray, indexinarray )[, invert] )

方法jquery.grep( array, function( elementofarray, indexinarray )[,

invert] )用于查找數組中滿足過濾函數的元素,原數組不會受影響。

如果參數invert未傳入或是false,元素隻有在過濾函數傳回true,或者傳回值可以轉換為true時,才會被儲存在最終的結果數組中,即傳回一個滿足回調函數的元素數組;如果參數invert是true,則情況正好相反,傳回的是一個不滿足回調函數的元素數組。

該方法的相關代碼如下所示:

grep: function( elems, callback, inv ) {

745        

var ret = [], retval;

746        

inv = !!inv;

747

748        

// go through the array, only saving the items

749        

// that pass the validator function

750        

for ( var i = 0, length = elems.length; i &lt; length; i++ ) {

751             retval = !!callback( elems[ i ], i

);

752             if ( inv !== retval ) {

753                 ret.push( elems[ i ] );

754             }

755        

756

757        

758    

第744行:定義方法jquery.grep( elems, callback, inv ),它接受3個參數:

參數array:待周遊查找的數組。

參數callback:過濾每個元素的函數,執行時被傳入兩個參數:目前元素和它的下标。該函數應該傳回一個布爾值。

參數inv:如果參數inv是false或未傳入,方法jquery.grep()會傳回一個滿足回調函數的元素數組;如果參數inv是true,則傳回一個不滿足回調函數的元素數組。

第746行:周遊數組elems,為每個元素執行過濾函數。如果參數inv為true,把執行結果為false的元素放入結果數組ret;如果inv為false,則把執行結果為true的元素放入結果數組ret。

第757行:最後傳回結果數組ret。

2.8.9 jquery.guid、jquery.proxy(

function, context )

1.?jquery.guid

屬性jquery.guid是一個全局計數器,用于jquery事件子產品和緩存子產品。在jquery事件子產品中,每個事件監聽函數會被設定一個guid屬性,用來唯一辨別這個函數;在緩存子產品中,通過在dom元素上附加一個唯一辨別,來關聯該元素和該元素對應的緩存。屬性jquery.guid初始值為1,使用時自增1,相關代碼如下所示:

793    

// a global guid counter for objects

// jquery.data( elem, name, data, pvt /*

internal use only */ )

1679                 elem[ internalkey ] = id =

++jquery.uuid;

// jquery.event.add: function( elem, types,

handler, data, selector )

2861        

    handler.guid = jquery.guid++;

2.?jquery.proxy( function, context )

方法jquery.proxy( function, context )接受一個函數,傳回一個新函數,新函數總是持有特定的上下文。這個方法有兩種用法:

(1)jquery.proxy(  function,

context )

參數function是将被改變上下文的函數,參數context是上下文。指定參數function的上下文始終為參數content。

(2)jquery.proxy( context, name )

參數name是參數context的屬性。指定參數name對應的函數的上下文始終為參數context。

796    

// bind a function to a context, optionally partially applying any

797    

// aguments.

proxy: function( fn, context ) {

799        

if ( typeof context === "string" ) {

800             var tmp = fn[ context ];

801             context = fn;

802             fn = tmp;

803        

804

805        

// quick check to determine if target is callable, in the spec

806        

// this throws a typeerror, but we will just return undefined.

807        

if ( !jquery.isfunction( fn ) ) {

808             return undefined;

809        

810

811        

// simulated bind

812        

var args = slice.call( arguments, 2 ),

813             proxy = function() {

814                 return fn.apply( context,

args.concat( slice.call( arguments ) ) );

815             };

816

817        

// set the guid of unique handler to the same of original handler, so it

can be removed

818    

    proxy.guid = fn.guid = fn.guid

|| proxy.guid || jquery.guid++;

819

820        

return proxy;

821    

第798行:定義方法jquery.proxy( fn, context ),參數有兩種格式:

jquery.proxy( fn, context )

jquery.proxy( context, name )

第799行:修正參數fn和context。如果第二個參數是字元串,說明參數格式是jquery.proxy( context, name ),修正為jquery.proxy( fn,

context )。

第807~809行:如果參數fn不是函數,則傳回undefined。

第812行:收集多餘參數。如果調用jquery.proxy()時,除了傳入參數fn、context之外,還傳入了其他參數,那麼在調用函數fn時,這些多餘的參數将會優先傳入。這裡借用數組方法slice()來擷取參數對象arguments中fn、context後的其他參數。下面的例子測試了傳入多餘參數的情況:

var proxied = $.proxy( function(){

console.log( this );               //

object

console.log( arguments ); // [1, 2,

3]

}, {}, 1, 2, 3 );

proxied(4, 5);

// 在控制台依次列印:

// object

// [1, 2, 3, 4, 5]

第813~815行:建立一個代理函數,在代理函數中調用原始函數fn,調用時通過方法apply()指定上下文。代理函數通過閉包機制引用context、args、slice。

第818行:為代理函數設定與原始函數相同的唯一辨別guid。如果原始函數沒有,則重新配置設定一個。

相同的唯一辨別将代理函數和原始函數關聯了起來。例如,在jquery事件系統中,如果為dom元素綁定了事件監聽函數的代理函數,當移除事件時,即使傳入的是原始函數,jquery也能通過唯一辨別guid移除正确的函數。

第820行:最後傳回建立的代理函數。

2.8.10 jquery.access(

elems, key, value, exec, fn( elem, key, value ), pass )

方法jquery.access( elems, key, value, exec, fn( elem, key, value ), pass

)可以為集合中的元素設定一個或多個屬性值,或者讀取第一個元素的屬性值。如果設定的屬性值是函數,并且參數exec是true時,還會執行函數并取其傳回值作為屬性值。

方法jquery.access()為.attr()、.prop()、.css()提供支援,這三個方法在調用jquery.access()時,參數exec為true,參數fn是同時支援讀取和設定屬性的函數(例jquery.attr()、jquery.prop()),相關代碼如下所示:

// .attr()

2166    

attr: function( name, value ) {

2167        

return jquery.access( this, name, value, true, jquery.attr );

2168    

// p.rop()

2176    

prop: function( name, value ) {

2177        

return jquery.access( this, name, value, true, jquery.prop );

2178    

// c.ss()

6460 jquery.fn.css = function( name, value

) {

6461    

// ...

6466    

return jquery.access( this, name, value, true, function( elem, name,

value ) {

6467        

return value !== undefined ?

6468            jquery.style( elem, name, value ) :

6469            jquery.css( elem, name );

6470    

});

6471 };

方法jquery.access( elems, key, value, exec, fn, pass )的相關代碼如下所示:

823    

// mutifunctional method to get and set values to a collection

824    

// the value/s can optionally be executed if it's a function

access: function( elems, key, value, exec, fn, pass ) {

826        

var length = elems.length;

827

828        

// setting many attributes

829        

if ( typeof key === "object" ) {

830             for ( var k in key ) {

831                 jquery.access( elems, k,

key[k], exec, fn, value );

832  

          }

833             return elems;

834        

835

836        

// setting one attribute

837        

if ( value !== undefined ) {

838             // optionally, function values get

executed if exec is true

839             exec = !pass &amp;&amp; exec

&amp;&amp; jquery.isfunction(value);

840

841             for ( var i = 0; i &lt; length;

i++ ) {

842                 fn( elems[i], key, exec ?

value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );

843             }

844

845             return elems;

846      

  }

847

848        

// getting an attribute

849        

return length ? fn( elems[0], key ) : undefined;

850    

第825行:定義方法jquery.access( elems, key, value, exec, fn, pass ),它接受 6 個參數:

參數elems:元素集合,通常是jquery對象。

參數key:屬性名或含有鍵值對的對象。

參數value:屬性值或函數。當參數key是對象時,該參數為undefined。

參數exec:布爾值,當屬性值是函數時,該參數訓示了是否執行函數。

參數fn:回調函數,同時支援讀取和設定屬性。

參數pass:布爾值,該參數在功能上與參數exec重疊,并且用法相當繁瑣,可以忽略這個參數。

第829~834行:如果參數key是對象,表示要設定多個屬性,則周遊參數key,為每個屬性遞歸調用方法jquery.access(),周遊完後傳回元素集合elems。

第837~846行:如果參數value不是undefined,表示要設定單個屬性,則周遊元素集合elems,為每個元素調用回調函數fn,周遊完後傳回元素集合elems。如果參數exec為true,并且參數value是函數,則執行參數value,并取其傳回值作為屬性值。

第849行:讀取一個屬性。如果元素集合elems不為空,則為第一個元素調用回調函數fn,讀取參數key對應的屬性值;否則傳回undefined。

2.8.11 jquery.error(

message )、jquery.noop()、jquery.now()

方法jquery.error( message )接受一個字元串,抛出一個包含了該字元串的異常。開發插件時可以覆寫這個方法,用來顯示更有用或更多的錯誤提示消息。

方法jquery.noop()表示一個空函數。當希望傳遞一個什麼也不做的函數時,可以使用這個空函數。開發插件時,這個方法可以作為可選回調函數的預設值,如果沒有提供回調函數,則執行jquery.noop()。

方法jquery.now()傳回目前時間的毫秒表示,是( newdate() ).gettime()的簡寫。

上面3個方法的相關代碼如下所示:

error: function( msg ) {

552        

throw new error( msg );

553    

now: function() {

853        

return ( new date() ).gettime();

854    

2.8.12 浏覽器嗅探:jquery.uamatch(

ua )、jquery.browser

屬性jquery.browser提供了通路目前頁面的浏覽器的資訊,其中包含最流行的4種浏覽器類型(ie、mozilla、webkit、opera)和版本資訊,屬性值的結構如下:

// jquery.browser

webkit/opera/msie/mozilla: true,

version: '版本号'

chrome和safari使用webkit作為核心引擎,是以如果jquery.browser.webkit為true則表示浏覽器是chrome或safari;如果jquery.browser.mozilla為true,則表示浏覽器是mozilla

firefox。

jquery.browser通過解析navigator.useragent來擷取浏覽器類型和版本号,這種技術也稱為浏覽器嗅探技術,用于解決浏覽器不相容問題;navigator是全局對象window的屬性,指向一個navigator對象,包含了正在使用的浏覽器的資訊;navigator.useragent包含了浏覽器用于http請求的使用者代理頭(user-agent)的值。

應該避免編寫基于特定浏覽器類型或版本号的代碼,因為這會導緻代碼與特定的浏覽器類型或版本緊密綁定在一起,另外,使用者或浏覽器也可以修改navigator.useragent,欺騙腳本和伺服器端;解決浏覽器不相容問題的更好做法是基于浏覽器功能測試編寫代碼,具體請參閱第7章。

對navigator.useragent的解析由方法jquery.uamatch( ua )實作,相關代碼如下所示:

 59    

// useragent regexp

 60    

rwebkit = /(webkit)[ \/]([\w.]+)/,

 61    

ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,

 62    

rmsie = /(msie) ([\w.]+)/,

 63    

rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

 74    

// keep a useragent string for use with jquery.browser

 75    

useragent = navigator.useragent,

856    

// use of jquery.browser is frowned upon.

857    

// more details: http:// docs.jquery.com/utilities/jquery.browser

uamatch: function( ua ) {

859        

ua = ua.tolowercase();

860

861        

var match = rwebkit.exec( ua ) ||

862             ropera.exec( ua ) ||

863             rmsie.exec( ua ) ||

864             ua.indexof("compatible")

&lt; 0 &amp;&amp; rmozilla.exec( ua ) ||

865             [];

866

867        

return { browser: match[1] || "", version: match[2] ||

"0" };

868    

899 browsermatch =

jquery.uamatch( useragent );

900 if (

browsermatch.browser ) {

901    

jquery.browser[ browsermatch.browser ] = true;

902    

jquery.browser.version = browsermatch.version;

903 }

904

905 // dprecated, use

jquery.browser.webkit instead

906 if (

jquery.browser.webkit ) {

907    

jquery.browser.safari = true;

908 }

第60~63行:定義用于解析使用者代理navigator.useragent的4個正規表達式:rwebkit、ropera、rmsie、rmozilla。每個正則包含兩個分組:浏覽器類型特征字元和浏覽器版本特征字元。

第858~868行:定義方法jquery.uamatch( ua ),用于解析目前浏覽器的類型和版本号。在方法jquery.uamatch( ua )中,依次嘗試用4個正規表達式比對使用者代理navigator.useragent,并傳回一個包含了比對結果的對象,對象的結構是:

browser: 分組 1 或空字元串,

version: 分組 2 或字元串"0"

第899~903行:調用方法jquery.uamatch( ua )解析使用者代理navigator.useragent,并把解析結果重新封裝為jquery.browser。

2.8.13 小結

構造jquery對象子產品的靜态屬性和方法總結如圖2-9所示。

繼續閱讀