天天看點

dojo/_base/lang源碼分析

 dojo/_base/lang子產品是一個工具子產品,但幾乎用dojo開發的app都會用到這個子產品。子產品中的方法能夠在某些開發場景中避免繁冗的代碼,接下來我們一起看看這些工具函數的使用和原理(僅僅是原理的實作,并非是dojo中的源碼)。

  lang.mixin(dest, sources...),這個函數的作用是将所有source中的屬性拷貝到dest中,并傳回dest。例子如下:

因為dest與source都是對象,而周遊對象中所有的屬性可以使用for-in。是以mixin的原理就是利用for-in将source中的所有屬性拷貝到dest中,如果某個屬性指向對象,我們隻做淺拷貝。原理實作:

  !(p in empty) || empty[p] !== source[p] 這句話是防止在safari的低版本浏覽器中,将tostring等object.prototype的某些屬性拷貝過去。但如果source中重寫了tostring,這個屬性是需要拷貝過去的。

  與mixin相關的還有lang.extend(ctor, props)這個函數。mixin的目的是從一個對象向另一個對象複制屬性,而extend的目的是将屬性複制到一個類的原型中。其主要的原理也是利用mixin:mixin(ctor.prototype, props)

  lang.getobject(prop, create, obj),這個函數是我很喜歡用的一個,如果要取一個對象中很深的一個屬性值,它能避免編寫繁冗的屬性層級判斷。舉個例子:

如果不使用這個函數,要取得“asdaf”,我們需要寫如下的一堆判斷:

這個函數的原理也比較簡單,将prop分割後,一層一層的去判斷下一層屬性是否存在。原理實作:

lang.setobject(name, value, context)函數與getobject一個是設值一個是取值。name是屬性串(如a.b.c),setobject的實作也要利用getprop,先取至倒數第二層的屬性,然後為最後一層指派,實作代碼如下:

lang.exists(name, obj)主要用來判斷一個對象中是否存在某個屬性,它也利用了getprop。

 但我在實際的工作中,發現這個函數并不如getobject好用,因為它僅僅以undefined來做判斷,如果屬性為null,這個函數仍然傳回true。是以不建議使用exists,最好還是使用getobject。

  lang.hitch(scope, method)函數目的是改變函數中this關鍵字的指向,它相當于bind函數,這個函數也是每個程式都要用到的。原理如下:

示例:

lang.delegate(obj),顧名思義為一個對象做代理,該函數的作用跟object.create函數在本質上是相同的。因為javascript中對象的易變性,可以很輕松的去修改一個對象的屬性。代理對象能在一定程度上保護原對象不被修改,而且代理比克隆的速度快。

 通過示例我們可以明白,隻能在一定程度上保護原對象不被修改。如果對象中的屬性都是基本類型,建議使用代理函數來代替克隆,否則的話還是老老實實的用克隆吧。

  lang.clone(/*anything*/ src),克隆函數也會經常被用到,dojo的克隆函數可以克隆任何變量,基本政策如下:

基本類型和函數執行個體直接傳回

dom對象,利用clonenode,克隆元素和元素的子元素(clonenode不會克隆事件)

date類型:return new date(src.gettime())

regexp類型:return new regexp(src)

數組類型,依次便利每個數組元素,并對每個元素都進行克隆

其他類型對象,利用src.constructor屬性

  原理實作如下:

 注意:最好不要去克隆不同frame中的對象

  

  lang.trim和lang.replace都是處理字元串的,一個是去除字元串頭尾的空白字元,一個是替換字元串。trim比較簡單,先來看一下:

replace(tmpl, map, pattern),用來将tmpl中比對pattern正則的部分用map中相應的屬性值來替換。先看幾個示例:

replace函數本質上是利用string自身的replace函數,原理實作如下:

lang子產品中,還有一部分istype函數,這些函數大家當做常識記住即可。

繼續閱讀