1. 程式人生 > >YUI學習總結(1 )

YUI學習總結(1 )

看了 YUI2 有一段時間了,在這紀錄一下自己的一些總結 。歡迎大家有不同的見解,可以給我留言。

再看英文文件及原始碼之前, 我試著 搜了下網路中寫的比較好的一些 YUI 總結:

在這裡列出(在些也感謝你們的分享):

先討論下YAHOO Global Object中的一些全域性功能函式

1. YAHOO.lang 中判斷型別的各種函式:

背景知識:

1,typeof是檢測能力最弱的一種檢測方式:typeof對型別的檢測只返回這幾種結果:number、string、boolean、object、function及undefined。對於基本資料型別的檢測還是可以滿足的,但對於物件型別檢測就有問題了,如果你測試typeof null、typeof {}、typeof window、typeof []、typeof new Date()發現他們都返回object

2,instanceof 存在iframe或其他不同頁面物件型別判斷時就會失效。

3,null 與 undefined 區別: null 是js的保留字(獨一無二的值),可以理解為無物件(因為typeof null =='object'),當null在布林環境下時,轉為false, 當在數字環境時轉為0,當在字串環境時轉為‘null’;undefined是js實現的全域性變數,是指未宣告的變數,或者是使用已經宣告但未賦值的變數,或者是使用了一個並不存在的物件屬性;當undefined 在布林環境下時,轉為false, 當在數字環境時轉為NaN,當在字串環境時轉為‘undefined ’;

 聯絡:null= = undefined 為true;

而YUInull, undefined, boolean, number, array, string, function,  object 八種類型進行了判斷。 內部程式碼實現是通過使用了 typeof 運算子 ,  Object.prototype.toString.call(), 及相互函式之間的呼叫來進行型別判斷。

分別總結如下:

(1) typeof: 為了從物件中區分出基本型別的。但陣列是 Object , 函式是 functionundefinedundefinednull 是 object。 相應知識連結: 這裡 (2) Object.prototype.toString.call

:是指使用最原始的 Object 的原型物件 prototypetoString 方法來判斷輸出的字串。 因為最原始的 Object 的原型物件 prototypetoString 方法返回的字串總為: [object ** ]  ,(其中 ** 可代表: Array  Function Object )

各函式主要程式碼:

isNull:  {  return o === null ;}

isUndefined : {  return typeof o === "undefined" }

isBoolean: {return typeof o == "boolean" }

isNumber: {return typeof == "number" } //isFinite 來檢測數字是否為有限的,即不是 NaN、負無窮或正無窮

isArray: { return ( Object.prototype.toString.call(o) =="[object Array]" ) }

isString: {return typeof o == "string"; }

isFunction: {return typeof o === "function" || ( Object.prototype.toString.call(o) =="[object function]" ) }

isObject:{return o&&( typeof o =="object"||isFunction(o) ) }  //認為Object 與 Function 都是 Object。

2, YAHOO.lang.extend ():

實現一個函式類的prototype(這裡把function稱為函式類)對另一個函式類的prototype的繼承,且有可選的用來重寫的屬性/方法。 函式簽名為:extend(subc, superc, overrides)

其中引數:subc為需要擴充套件的函式(function),superc為被繼承的函式 (function) , overrides為要重寫的屬性/方法

在 extend 方法中,首先構造了一個空函式,並使空函式的prototype指向superc的prototype,再new 該空函式物件並賦值給subc.prototype。(為什麼不直接new superc(),這樣就運行了superc的函式構造體,可能父類的建構函式需要引數時建立父類例項時會出錯,如父類的建構函式運行了this.name="xujia")。接著修改subc.prototype.constructor指向自己,即subc函式,以免建立子類例項時會丟失 constructor 屬性。 然後還特別給subc.prototype增加屬性superclass,並指向為superc.prototype。這樣就能得到了整條的父子關係繼承鏈。

程式碼如下:

接著進行多個屬性/方法的重寫:主要利用for in 列舉overrides物件的屬性或方法p,再利用hasOwnProperty()判斷,如果p是overrides物件自己本地屬性/方法(不是從prototype原型中得到的),就重寫subc.prototype中的屬性/方法。最後考慮IE不能for in 枚舉出overrides中可能已被重寫的Object.prototype中的原生native函式。

程式碼如下:

從程式碼中可以看出,我們定義子函式類就可以:

3,YAHOO.lang.augmentObject():

實現了用一個物件source的屬性/方法對另一個物件result的擴充套件,使obj1也能擁有自己沒有但在obj2中有的屬性/方法。而且可以通過多個可選的引數來處理重寫。通常用於合併配置物件與預設配置物件。

函式的宣告為:augmentObject(r, s, oneProperty,two, ...)

可以看出augmentObject 有三種呼叫方法,分別是:

augmentObject(result, source),一般情況下用些方法,從 source 引入 result 中沒有的屬性;

augmentObject(result, source, override),override 設定是否覆蓋,如果是 true 的話,那麼 source 中所有屬性會覆蓋 result 中已有的屬性;

augmentObject(result, source, ovrride_name, ...),指定要覆蓋屬性的列表,source 引數後為要覆蓋屬性名稱的列表(且即使result中沒有而source中有的屬性或方法也不擴充套件),例如覆蓋 result 中的 toString 和 valueOf,那麼可以呼叫 augmentObject(result, source, "toString", "valueOf")來實現。

原始碼中造成這三種不同分支的原因如下:

當然合併物件的最後同樣呼叫了 _IEEnumFix 方法來修正 IE 中不列舉與內部屬性同名屬性的 bug。

這裡例子就不取了,可以看YUI的examples。

4,YAHOO.lang.augmentProto():

 相應原始碼如下:

因此從這裡看出,我們可以用extendaugmentProto函式來給一個函式類擴充套件方法/屬性。但它們兩者還是有區別的,主要體現在instanceof運算上,測試如下:

PS:有關javascript中instanceof運算子的執行原理,及它與prototype的關係的瞭解,可以看我的曾寫過的一篇總結

augmentProto 與 augmentObject 呼叫方式和實現原理基本相同,只不過後者是處理物件,而前者是處理函式的 prototype,它是通過使用兩個引數的 prototype 來構造一個引數列表,傳遞給 augmentObject 物件來實現 augmentProto 的功能。