讀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的值;javascript

$.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,
    // ...
  })
  • 準備工做作完,就能夠進行對象的判斷了;java

    • 首先封裝一個判斷方法,根據這個方法的返回值來判斷對象的類型;
    //好比,若是要判斷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
    • 下面根據上面的封裝方法返回值判斷類型;node

      • 判斷函數
      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
  • 用法
    java $.camelCase('hello-there') //=> "helloThere" $.camelCase('helloThere') //=> "helloThere"
  • str.replcace(a,b)json

    將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)選取傳入參數的第一個參數到最後一個參數;app

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爲類數組對象或者對象;dom

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

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

    這裏巧妙應用了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)
}
  • 去除字符串開頭和結尾的空格
相關文章
相關標籤/搜索