讀zepto核心源碼學習JS筆記(2)--工具函數

1. $.type $.isArray $.isFunction $.isNumeric $.isPlainObject $.isWindow

  • 判斷對象的方法介紹
    在zepto源碼中,使用了Object.prototype.toString.call()方法判斷對象的類型,以下簡單介紹下此方法的大致情況
//null
Object.prototype.toString.call(null);//”[object Null]”
//undefined
Object.prototype.toString.call(undefined);//”[object Undefined]”
//string
Object.prototype.toString.call(“aaa”);//”[object String]”
//number
Object.prototype.toString.call(111);//”[object Number]”
//boolean
Object.prototype.toString.call(true);//”[object Boolean]”
//函數
Function fn(){console.log(“xixi”);}
Object.prototype.toString.call(fn);//”[object Function]”
//數組類型
var arr = [1,2,,3,4];
Object.prototype.toString.call(arr);//”[object Array]”
//日期
var date = new Date();
Object.prototype.toString.call(date);//”[object Date]”
//自定義類型
//不能判斷aa是不是AA的實例,要用instanceof判斷
function AA(a, b) {
    this.a = a;
    this.b = b;
}
var aa = new AA("xixi", 'haha');
Object.prototype.toString.call(aa); //”[object Object]”
Object.prototype.toString.call(aa); //”[object Object]”
//正則
var aa = /^\w$/
Object.prototype.toString.call(aa); //”[object RegExp]”
  • 在zepto中,先定義了一個空對象class2type,并取出對象函數自帶的toString方法,即為Object.prototype.toString.call()
class2type = {},
toString = class2type.toString,

然后填充class2type的值;

$.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type["[object " + name + "]"] = name.toLowerCase()
    //最終結果
    //class2type[”[object Boolean]”] = boolean,
    //class2type[”[object Number]”] = number,
    //class2type[”[object String]”] = string,
    // ...
  })
  • 準備工作做完,就可以進行對象的判斷了;

    • 首先封裝一個判斷方法,根據這個方法的返回值來判斷對象的類型;
    //比如,如果要判斷function aa(){};則返回class2type[Object.prototype.toString.call(aa)]==class2type[”[object Function]”]==function;所以就判斷出為函數
    function type(obj) {
     //如果obj為null或者undefined,返回字符串'null','undefined';否則返回class2type[]或者object
          return obj == null ? String(obj) :class2type[toString.call(obj)] || "object"
    }
    
    $.type = type
    
    • 下面根據上面的封裝方法返回值判斷類型;

      • 判斷函數
      function isFunction(value) {
          return type(value) == "function"
        }
      
      $.isFunction = isFunction
      
      • 判斷window;根據widow自己的屬性來判斷;window.window = window;
      function isWindow(obj) {
          return obj != null && obj == obj.window
        }
      
      $.isWindow = isWindow
      
      • 判斷document
      function isDocument(obj) {
          return obj != null && obj.nodeType == obj.DOCUMENT_NODE
        }
      
      • 判斷是否為對象
      function isObject(obj) {
          return type(obj) == "object"
        }
      
      • 對于通過字面量定義的對象和new Object的對象返回true,new Object時傳參數的返回false
      function isPlainObject(obj) {
          return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
        }
      
      $.isPlainObject = isPlainObject
      
      • 判斷數組
      function isArray(value) {
          return value instanceof Array
        }
      
      $.isArray = isArray
      
      • 判斷類數組
      function likeArray(obj) {
          return typeof obj.length == 'number'
        }
      
      • 空對象
      $.isEmptyObject = function(obj) {
          var name
          for (name in obj) return false
          return true
        }
      
      • 有限數值或者字符串表達的數字
      $.isNumeric = function(val) {
          var num = Number(val), type = typeof val
          return val != null && type != 'boolean' &&
            (type != 'string' || val.length) &&
            !isNaN(num) && isFinite(num) || false
        }
      

2. $.camelCase

camelize = function(str){ 
    return str.replace(/-+(.)?/g,
        function(match, chr){ return chr ? chr.toUpperCase() : '' }
    ) 
}
$.camelCase = camelize
  • 用法

    $.camelCase('hello-there') //=> "helloThere"
    $.camelCase('helloThere')  //=> "helloThere"
    
  • str.replcace(a,b)

    將str中的a替換成b;上面代碼中將b用了函數返回值來表達;

3. $.contain

//為了判斷某個節點是不是另一個節點的后代,瀏覽器引入了contains()方法;
$.contains = document.documentElement.contains ?
//如果瀏覽器支持contains()方法,就執行這個函數
    function(parent, node) {
      return parent !== node && parent.contains(node)
    } :
    //否則循環判斷
    function(parent, node) {
      while (node && (node = node.parentNode))
        if (node === parent) return true
      return false
}
  • 檢查父節點是否包含給定的dom節點,如果兩者是相同的節點,則返回false

4. $.each

$.each = function(elements, callback){
    var i, key
    if (likeArray(elements)) {
      for (i = 0; i < elements.length; i++)
        if (callback.call(elements[i], i, elements[i]) === false) return elements
    } else {
      for (key in elements)
        if (callback.call(elements[key], key, elements[key]) === false) return elements
    }

    return elements
}
  • 遍歷,將每次循環的值作為callback的上下文;如果callback返回的結果為false,遍歷停止;

5. $.extend

function extend(target, source, deep) {
    for (key in source)
    //如果是神拷貝,source[key]是對象或者數組
      if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
      //source[key]是對象,而target[key]不是對象
        if (isPlainObject(source[key]) && !isPlainObject(target[key]))
          target[key] = {}
      //source[key]是數組,而target[key]不是數組
        if (isArray(source[key]) && !isArray(target[key]))
          target[key] = []
          //遞歸
        extend(target[key], source[key], deep)
      }
      else if (source[key] !== undefined) target[key] = source[key]
  }
$.extend = function(target){
    var deep, args = slice.call(arguments, 1)
    //如果傳入的第一個參數為布爾值
    if (typeof target == 'boolean') {
      deep = target
     //將除第一個參數外的參數賦值給target
      target = args.shift()
    }
    //遍歷參數,將參數都復制到target上;
    args.forEach(function(arg){ extend(target, arg, deep) })
    return target
  }
  • 我們首先看一下用法;
$.extend(target, [source, [source2, ...]])   ? target
$.extend(true, target, [source, ...])   ? target v1.0+
var target = { one: 'patridge' },
source = { two: 'turtle doves' }
$.extend(target, source)//{one: "patridge", two: "turtle doves"}
  • target代表被拓展的對象,source為源對象;deep代表是深復制還是淺復制;

    • 對于字符串來說,淺復制是對值的復制,,對于對象來說,淺復制是對對象地址的復制,兩者共同指向同一個地址,其中一個改變,另一個對象也會隨之改變,而深復制是在堆區中開辟一個新的,兩個對象則指向不同的地址,相互獨立;
  • slice.call(arguments, 1)選取傳入參數的第一個參數到最后一個參數;

5. $.inArray

$.inArray = function(elem, array, i){
    return emptyArray.indexOf.call(array, elem, i)
}
  • 用法
$.inArray("abc",["bcd","abc","edf","aaa"]);//=>1
$.inArray("abc",["bcd","abc","edf","aaa"],1);//=>1
$.inArray("abc",["bcd","abc","edf","aaa"],2);//=>-1
  • 返回數組中指定元素的索引值,如果沒有找到該元素則返回-1。

6. $.map

$.map = function(elements, callback){
    var value, values = [], i, key
    if (likeArray(elements))
      for (i = 0; i < elements.length; i++) {
        value = callback(elements[i], i)
        if (value != null) values.push(value)
      }
    else
      for (key in elements) {
        value = callback(elements[key], key)
        if (value != null) values.push(value)
      }
    return flatten(values)
 }
  • element為類數組對象或者對象;

    • 如果為類數組對象的話,用for循環
    • 如果為對象的話,用fo.....in....循環
    • 再將索引和值傳給callback,
    • 如果callback的返回值不是null或者undefined,存入新的數組
    • 最后將數組扁平化flatten()---數組降維,二維數組轉為一維數組
  • flatten()

    function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }

    這里巧妙應用了apply方法,apply方法的第一個元素會被當作this,第二個元素被做為傳入的參數arguments;
    例如:concat.apply([],[[1],[2],[3]]),等價于[].concat([1],[2],[3]),輸出的值為[1,2,3],就實現了數組的扁平化;

7. $.noop

$.noop = function() {}
  • 引用空函數

8. $.parseJSON

if (window.JSON) $.parseJSON = JSON.parse
  • 原生JSON.parse的別名;接受一個JSON字符串,返回解析后的javascript對象。

9. $.trim

$.trim = function(str) {
    return str == null ? "" : String.prototype.trim.call(str)
}
  • 去除字符串開頭和結尾的空格
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容

  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,799評論 2 17
  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創建,需要時才創建 最常見的單例模式,...
    Obeing閱讀 2,088評論 1 10
  • 三、閉包和高階函數 3.1 閉包 3.1.1 變量的作用域 所謂變量的作用域,就是變量的有效范圍。通過作用域的劃分...
    梁同學de自言自語閱讀 1,480評論 0 6
  • 第一次聽到母親哭泣是1998年,那一年我上二年級,面對三個上門的村干部催繳集資,母親手里拿不出錢,急得團團轉......
    阿土127閱讀 409評論 0 4
  • 世界上的事啊,真奇怪,真真假假,挺讓人覺得唏噓。——大栗致自己 這兩天,我學習了如何排版和剪輯視頻。沒學之前,總給...
    有杕之杜閱讀 504評論 1 3