国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Zepto核心模塊之工具方法拾遺

lcodecorex / 2284人閱讀

摘要:舉例需要注意的是,此時(shí)回調(diào)函數(shù)中的指向的就是數(shù)組或者對(duì)象的某一項(xiàng)。中提供的拷貝方法,默認(rèn)為淺拷貝,如果第一個(gè)參數(shù)為布爾值則表示深拷貝。

前言

平時(shí)開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)用類(lèi)似eachmapforEach之類(lèi)的方法,Zepto本身也把這些方法掛載到$函數(shù)身上,作為靜態(tài)方法存在,既可以給Zepto的實(shí)例使用,也能給普通的js對(duì)象使用。今天我們主要針對(duì)其提供的這些api做一些源碼實(shí)現(xiàn)分析。

源碼倉(cāng)庫(kù)
原文鏈接

具體各個(gè)api如何使用可以參照英文文檔Zepto.js 中文文檔Zepto.js

1. $.camelCase

該方法主要是將連字符轉(zhuǎn)化成駝峰命名法。例如可以將a-b-c這種形式轉(zhuǎn)換成aBC,當(dāng)然連字符的數(shù)量可以是多個(gè),a---b-----c => aBC,具體實(shí)現(xiàn)已經(jīng)在這些Zepto中實(shí)用的方法集說(shuō)過(guò)了,可以點(diǎn)擊查看。而其代碼也只是將camelize函數(shù)賦值給了$.camelCase

$.camelCase = camelize
2. $.contains

$.contains(parent, node) ? boolean該方法主要用來(lái)檢測(cè)parent是否包含給定的node節(jié)點(diǎn)。如果parent和node為同一節(jié)點(diǎn),則返回false。

舉例

  • 1
  • 2
let oList = document.querySelector(".list")
let oItem = document.querySelector(".item")
let oTest = document.querySelector(".test")

console.log($.contains(oList, oItem)) // true 父子節(jié)點(diǎn)
console.log($.contains(oList, oList)) // false 同一節(jié)點(diǎn)
console.log($.contains(oList, oTest)) // false 兄弟節(jié)點(diǎn)

源碼

$.contains = document.documentElement.contains ?
  function (parent, node) {
    // 防止parent和node傳相同的節(jié)點(diǎn),故先parent !== node
    // 接著就是調(diào)用原生的contains方法判斷了
    return parent !== node && parent.contains(node)
  } :
  function (parent, node) {
    // 當(dāng)node節(jié)點(diǎn)存在,就把node的父節(jié)點(diǎn)賦值給node
    while (node && (node = node.parentNode))
      // 如果node的父節(jié)點(diǎn)和parent相等就返回true,否則繼續(xù)向上查找
      // 其實(shí)有一個(gè)疑問(wèn),為什么開(kāi)頭不先排查node === parent的情況呢
      // 不然經(jīng)過(guò)循環(huán)最后卻得到false,非常的浪費(fèi)
      if (node === parent) return true
    return false
  }

用了document.documentElement.contains做判斷,如果瀏覽器支持該方法,就用node.contains重新包了一層得到一個(gè)函數(shù),差別就在于如果傳入的兩個(gè)節(jié)點(diǎn)相同,那么原生的node.contains返回true,具體用法可以查看MDN Node.contains但是$.contains返回false

如果原生不支持就需要我們自己寫(xiě)一個(gè)方法了。主要邏輯還是通過(guò)一個(gè)while循環(huán),判斷傳入的node節(jié)點(diǎn)的父節(jié)點(diǎn)是否為parent,如果一個(gè)循環(huán)下來(lái),還不是最后才返回false

其實(shí)這里應(yīng)該是可以做一個(gè)優(yōu)化的,一進(jìn)來(lái)的時(shí)候就先判斷兩個(gè)節(jié)點(diǎn)是否為同一節(jié)點(diǎn),不是再進(jìn)行后續(xù)的判斷

3. $.each

用來(lái)遍歷數(shù)組或者對(duì)象,類(lèi)似原生的forEach但是不同的是,可以中斷循環(huán)的執(zhí)行,并且服務(wù)對(duì)象不局限于數(shù)組。

舉例

let testArr = ["qianlongo", "fe", "juejin"]
let testObj = {
  name: "qianlongo",
  sex: "boy"
}

$.each(testArr, function (i, val) {
  console.log(i, val)
})

// 0 "qianlongo"
// 1 "fe"
// 2 "juejin"

$.each(testObj, function (key, val) {
  console.log(key, val)
})

// name qianlongo
// sex boy

需要注意的是,此時(shí)回調(diào)函數(shù)中的this指向的就是數(shù)組或者對(duì)象的某一項(xiàng)。這樣主要是方便內(nèi)部的一些其他方法在遍歷dom節(jié)點(diǎn)的時(shí)候,this很方便地就指向了對(duì)應(yīng)的dom

源碼實(shí)現(xiàn)

$.each = function (elements, callback) {
  var i, key
  // 如果是類(lèi)數(shù)組就走這個(gè)if
  if (likeArray(elements)) {
    for (i = 0; i < elements.length; i++)
      // 可以看到用.call去執(zhí)行了callback,并且第一個(gè)參數(shù)是數(shù)組中的item
      // 如果用來(lái)遍歷dom,那么內(nèi)部的this,指的就是當(dāng)前這個(gè)元素本身
      // 判斷callback執(zhí)行的結(jié)果,如果是false,就中斷遍歷
      // 中斷遍歷這就是和原生forEach不同的地方
      // 2017-8-16添加,原生的forEach內(nèi)部的this指向的是數(shù)組本身,但是這里指向的是數(shù)組的項(xiàng)
      // 2017-8-16添加,原生的forEach回調(diào)函數(shù)的參數(shù)是val, i...,這里反過(guò)來(lái)
      if (callback.call(elements[i], i, elements[i]) === false) return elements
  } else {
    // 否則回去走for in循環(huán),邏輯與上面差不多
    for (key in elements)
      if (callback.call(elements[key], key, elements[key]) === false) return elements
  }

  return elements
}

likeArray已經(jīng)在這些Zepto中實(shí)用的方法集說(shuō)過(guò)了,可以點(diǎn)擊查看。

4. $.extend

Zepto中提供的拷貝方法,默認(rèn)為淺拷貝,如果第一個(gè)參數(shù)為布爾值則表示深拷貝。

源碼實(shí)現(xiàn)

$.extend = function (target) {
  // 將第一個(gè)參數(shù)之外的參數(shù)變成一個(gè)數(shù)組
  var deep, args = slice.call(arguments, 1)
  // 處理第一個(gè)參數(shù)是boolean值的情況,默認(rèn)是淺復(fù)制,深復(fù)制第一個(gè)參數(shù)傳true
  if (typeof target == "boolean") {
    deep = target
    target = args.shift()
  }
  // $.extend(true, {}, source1, source2, source3)
  // 有可能有多個(gè)source,遍歷調(diào)用內(nèi)部extend方法,實(shí)現(xiàn)復(fù)制
  args.forEach(function (arg) { extend(target, arg, deep) })
  return target
}

可以看到首先對(duì)第一個(gè)參數(shù)是否為布爾值進(jìn)行判斷,有意思的是,只要是布爾值都表示深拷貝,你傳true或者false都是一個(gè)意思。接著就是對(duì)多個(gè)source參數(shù)進(jìn)行遍歷調(diào)用內(nèi)部方法extend

接下來(lái)我們主要來(lái)看內(nèi)部方法extend

function extend(target, source, deep) {
  // 對(duì)源對(duì)象source進(jìn)行for in遍歷
  for (key in source)
    // 如果source[key]是純對(duì)象或者數(shù)組,并且指定為深復(fù)制
    if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
      // 如果source[key]為純對(duì)象,但是target[key]不是純對(duì)象,則將目標(biāo)對(duì)象的key設(shè)置為空對(duì)象
      if (isPlainObject(source[key]) && !isPlainObject(target[key]))
        target[key] = {}
      // 如果  如果source[key]為數(shù)組,但是target[key]不是數(shù)組,則將目標(biāo)對(duì)象的key設(shè)置為數(shù)組
      if (isArray(source[key]) && !isArray(target[key]))
        target[key] = []
      // 遞歸調(diào)用extend函數(shù)  
      extend(target[key], source[key], deep)
    }
    // 淺復(fù)制或者source[key]不為undefined,便進(jìn)行賦值
    else if (source[key] !== undefined) target[key] = source[key]
}

整體實(shí)現(xiàn)其實(shí)還挺簡(jiǎn)單的,主要是遇到對(duì)象或者數(shù)組的時(shí)候,并且指定為深賦值,則遞歸調(diào)用extend本身,從而完成復(fù)制過(guò)程。

5. $.grep

其實(shí)就是數(shù)組的原生方法filter,最終結(jié)果得到的是一個(gè)數(shù)組,并且只包含回調(diào)函數(shù)中返回 true 的數(shù)組項(xiàng)

直接看源碼實(shí)現(xiàn)

$.grep = function (elements, callback) {
  return filter.call(elements, callback)
}

通過(guò)call形式去調(diào)用原生的數(shù)組方法 filter,過(guò)濾出符合條件的數(shù)據(jù)項(xiàng)。

6. $.inArray

返回?cái)?shù)組中指定元素的索引值,沒(méi)有找到該元素則返回-1,fromIndex是一個(gè)可選的參數(shù),表示從哪個(gè)地方開(kāi)始往后進(jìn)行查找。

$.inArray(element, array, [fromIndex]) ? number

舉例

let testArr = [1, 2, 3, 4]

console.log($.inArray(1, testArr)) // 0
console.log($.inArray(4, testArr)) // 3
console.log($.inArray(-10, testArr)) // -1
console.log($.inArray(1, testArr, 2)) // -1

源碼實(shí)現(xiàn)

$.inArray = function (elem, array, i) {
  return emptyArray.indexOf.call(array, elem, i)
}

可見(jiàn)其內(nèi)部也是調(diào)用的原生indexOf方法。

7. $.isArray

判斷obj是否為數(shù)組。

我們知道判斷一個(gè)值是否為對(duì)象,方式其實(shí)挺多的,比如下面的這幾種方式

// 1. es5中的isArray

console.log(Array.isArray([])) // true

// 2. 利用instanceof判斷

console.log([] instanceof Array) // true

// 3. 最好的方式 toString
console.log(Object.prototype.toString.call([]) === "[object Array]") // true

而Zepto中就是采用的第二種方式

var isArray = Array.isArray || function (object) {     return object instanceof Array
}

$.isArray = isArray

如果支持isArray方法就用原生支持的,否則通過(guò)instanceof判斷,其實(shí)不太清楚為什么第二種方式,我們都知道這是有缺陷的,在有iframe場(chǎng)景下,就會(huì)出現(xiàn)判斷不準(zhǔn)確的情況.

8. $.isFunction

判斷一個(gè)值是否為函數(shù)類(lèi)型

源碼實(shí)現(xiàn)

function isFunction(value) { 
  return type(value) == "function" 
}

$.isFunction = isFunction

主要還是通過(guò)內(nèi)部方法type來(lái)實(shí)現(xiàn)的,詳情可以點(diǎn)擊這些Zepto中實(shí)用的方法集查看。

9. $.isNumeric

如果傳入的值為有限數(shù)值或一個(gè)字符串表示的數(shù)字,則返回ture。

舉例

$.isNumeric(null) // false
$.isNumeric(undefined) // false
$.isNumeric(true) // false
$.isNumeric(false) // false
$.isNumeric(0) // true
$.isNumeric("0") // true
$.isNumeric("") // false
$.isNumeric(NaN) // false
$.isNumeric(Infinity) // false
$.isNumeric(-Infinity) // false

源碼

$.isNumeric = function (val) {
  var num = Number(val), type = typeof val
  return val != null && type != "boolean" &&
    (type != "string" || val.length) &&
    !isNaN(num) && isFinite(num) || false
}

首先val經(jīng)過(guò)Number函數(shù)轉(zhuǎn)化,得到num,然后獲取val的類(lèi)型得到type

我們來(lái)回顧一下Number(val)的轉(zhuǎn)化規(guī)則,這里截取一張圖。

看起來(lái)轉(zhuǎn)化規(guī)則非常復(fù)雜,但是有幾點(diǎn)我們可以確定,

如果輸入的是數(shù)字例如1,1.3那轉(zhuǎn)化后的還是數(shù)字,

如果輸入的是字符串?dāng)?shù)字類(lèi)型例如"123", "12.3"那轉(zhuǎn)化后的也是數(shù)字

如果輸入的是空字符串""那轉(zhuǎn)化后得到的是0

如果輸入是類(lèi)似字符串"123aaa",那轉(zhuǎn)化后得到的是NaN

所以再結(jié)合下面的判斷

通過(guò)val != null排除掉nullundefined

通過(guò)type != "boolean"排除掉,truefalse

通過(guò)isFinite(num)限定必須是一個(gè)有限數(shù)值

通過(guò)!isNaN(num)排除掉被Number(val)轉(zhuǎn)化為NaN的值

(type != "string" || val.length), val為字符串,并且字符串的長(zhǎng)度大于0,排除""空字符串的場(chǎng)景。

以上各種判斷下來(lái)基本就滿足了這個(gè)函數(shù)原來(lái)的初衷要求。

9. $.isPlainObject

測(cè)試對(duì)象是否是“純粹”的對(duì)象,這個(gè)對(duì)象是通過(guò) 對(duì)象常量("{}") 或者 new Object 創(chuàng)建的,如果是,則返回true

10. $.isWindow

如果object參數(shù)為一個(gè)window對(duì)象,那么返回true

該兩個(gè)方法在這些Zepto中實(shí)用的方法集也聊過(guò)了,可以點(diǎn)擊查看一下。

11. $.map

和原生的map比較相似,但是又有不同的地方,比如這里的map得到的記過(guò)有可能不是一一映射的,也就是可能得到比原來(lái)數(shù)組項(xiàng)數(shù)更多的數(shù)組,以及這里的map是可以用來(lái)遍歷對(duì)象的。

我們先看幾個(gè)例子

let testArr = [1, 2, null, undefined]
let resultArr1 = $.map(testArr, (val, i) => {
  return val
})
let resultArr2 = $.map(testArr, (val, i) => {
  return [val, [val]]
})

// 再來(lái)看看原生的map的表現(xiàn)
let resultArr3 = testArr.map((val, i) => {
  return val
})
let resultArr4 = testArr.map((val, i) => {
  return [val, [val]]
})

運(yùn)行結(jié)果如下

可以看出

resultArr1resultArr3的區(qū)別是$.mapundefinednull給過(guò)濾掉了。

resultArr2resultArr4的區(qū)別是$.map把回調(diào)函數(shù)的返回值給鋪平了。

接下來(lái)看看源碼是怎么實(shí)現(xiàn)的。

 $.map = function (elements, callback) {
  var value, values = [], i, key
  // 如果是類(lèi)數(shù)組,則用for循環(huán)
  if (likeArray(elements))
    for (i = 0; i < elements.length; i++) {
      value = callback(elements[i], i)
      // 如果callback的返回值不為null或者undefined,就push進(jìn)values
      if (value != null) values.push(value)
    }
  else
    // 對(duì)象走這個(gè)邏輯
    for (key in elements) {
      value = callback(elements[key], key)
      if (value != null) values.push(value)
    }
  // 最后返回的是只能鋪平一層數(shù)組 
  return flatten(values)
}

從源碼實(shí)現(xiàn)上可以看出因?yàn)?b>value != null以及flatten(values)造成了上述差異。

12. $.noop

其實(shí)就是引用一個(gè)空的函數(shù),什么都不處理,那它到底有啥用呢?

比如。我們定義了幾個(gè)變量,他未來(lái)是作為函數(shù)使用的。

let doSomeThing = () => {}
let doSomeThingElse = () => {}

如果直接這樣

let doSomeThing = $.noop
let doSomeThingElse = $.noop

宿主環(huán)境就不必為我們創(chuàng)建多個(gè)匿名函數(shù)了。

其實(shí)還有一種可能用的不多的場(chǎng)景,在判斷一個(gè)變量是否是undefined的時(shí)候,可以用到。因?yàn)楹瘮?shù)沒(méi)有返回值,默認(rèn)返回undefined,也就是排除了那些老式瀏覽器undefined可以被修改的情況

if (xxx === $.noop()) {
  // xxx
}
13. $.parseJSON

原生JSON.parse方法的別名,接收的是一個(gè)字符串對(duì)象,返回一個(gè)對(duì)象。

源碼實(shí)現(xiàn)

$.parseJSON = JSON.parse
14. $.trim

刪除字符串首尾的空白符,如果傳入nullundefined返回空字符串

源碼實(shí)現(xiàn)

$.trim = function (str) {
  return str == null ? "" : String.prototype.trim.call(str)
}
15. $.type

獲取JavaScript 對(duì)象的類(lèi)型。可能的類(lèi)型有: null undefined boolean number string function array date regexp object error.

該方法內(nèi)部實(shí)現(xiàn)其實(shí)就是內(nèi)部的type函數(shù),并且已經(jīng)在這些Zepto中實(shí)用的方法集聊過(guò)了,可以點(diǎn)擊查看。

$.type = type
結(jié)尾

Zepto大部分工具方法或者說(shuō)靜態(tài)方法就是這些了,歡迎大家指正其中的錯(cuò)誤和問(wèn)題。

參考資料

讀zepto源碼之工具函數(shù)

MDN trim

MDN typeof

MDN isNaN

MDN Number

MDN Node.contains

文章記錄

原來(lái)你是這樣的jsonp(原理與具體實(shí)現(xiàn)細(xì)節(jié))

誰(shuí)說(shuō)你只是"會(huì)用"jQuery?

向zepto.js學(xué)習(xí)如何手動(dòng)觸發(fā)DOM事件

mouseenter與mouseover為何這般糾纏不清?

這些Zepto中實(shí)用的方法集

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/51191.html

相關(guān)文章

  • Zepto核心模塊工具方法拾遺

    摘要:舉例需要注意的是,此時(shí)回調(diào)函數(shù)中的指向的就是數(shù)組或者對(duì)象的某一項(xiàng)。中提供的拷貝方法,默認(rèn)為淺拷貝,如果第一個(gè)參數(shù)為布爾值則表示深拷貝。 前言 平時(shí)開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)用類(lèi)似each、map、forEach之類(lèi)的方法,Zepto本身也把這些方法掛載到$函數(shù)身上,作為靜態(tài)方法存在,既可以給Zepto的實(shí)例使用,也能給普通的js對(duì)象使用。今天我們主要針對(duì)其提供的這些api做一些源碼實(shí)現(xiàn)分析。 源...

    Alex 評(píng)論0 收藏0
  • zepto源碼分析form模塊

    摘要:形如源代碼在的原型上添加了相關(guān)方法。類(lèi)似源代碼每個(gè)表單的和都通過(guò)編碼最后通過(guò)符號(hào)分割有了的基礎(chǔ),就是將相應(yīng)的和都通過(guò)編碼,然后用符號(hào)進(jìn)行分割,也就達(dá)到了我們要的結(jié)果。 前言 JavaScript最初的一個(gè)應(yīng)用場(chǎng)景就是分擔(dān)服務(wù)器處理表單的責(zé)任,打破處處依賴(lài)服務(wù)器的局面,這篇文章主要介紹zepto中form模塊關(guān)于表單處理的幾個(gè)方法,serialize、serializeArray、sub...

    Muninn 評(píng)論0 收藏0
  • Zepto中數(shù)據(jù)緩存原理與實(shí)現(xiàn)

    摘要:有一個(gè)模塊,專(zhuān)門(mén)用來(lái)做數(shù)據(jù)緩存,允許我們存放任何與相關(guān)的數(shù)據(jù)。在匹配元素上存儲(chǔ)任意相關(guān)數(shù)據(jù)或返回匹配的元素集合中的第一個(gè)元素的給定名稱(chēng)的數(shù)據(jù)存儲(chǔ)的值。確定元素是否有與之相關(guān)的數(shù)據(jù)。 前言 以前我們使用Zepto進(jìn)行開(kāi)發(fā)的時(shí)候,會(huì)把一些自定義的數(shù)據(jù)存到dom節(jié)點(diǎn)上,好處是非常直觀和便捷,但是也帶來(lái)了例如直接將數(shù)據(jù)暴露出來(lái)會(huì)出現(xiàn)安全問(wèn)題,數(shù)據(jù)以html自定義屬性標(biāo)簽存在,對(duì)于瀏覽器本身來(lái)說(shuō)...

    macg0406 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<