<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          研究Vue源碼時(shí)發(fā)現(xiàn)的一些好玩函數(shù)

          共 903字,需瀏覽 2分鐘

           ·

          2020-10-17 16:24

          作者:chinamasters
          https://segmentfault.com/a/1190000025157159

          最近在深入研究vue源碼,把學(xué)習(xí)過(guò)程中,看到的一些好玩的的函數(shù)方法收集起來(lái)做分享,希望對(duì)大家對(duì)深入學(xué)習(xí)js有所幫助。如果大家都能一眼看懂這些函數(shù),說(shuō)明技術(shù)還是不錯(cuò)的哦。

          1. 數(shù)據(jù)類(lèi)型判斷

          Object.prototype.toString.call()返回的數(shù)據(jù)格式為?[object Object]類(lèi)型,然后用slice截取第8位到倒一位,得到結(jié)果為?Object

          var?_toString?=?Object.prototype.toString;
          function?toRawType?(value)?{
          ??return?_toString.call(value).slice(8,?-1)
          }

          運(yùn)行結(jié)果測(cè)試

          toRawType({})?//??Object?
          toRawType([])??//?Array????
          toRawType(true)?//?Boolean
          toRawType(undefined)?//?Undefined
          toRawType(null)?//?Null
          toRawType(function(){})?//?Function

          2. 利用閉包構(gòu)造map緩存數(shù)據(jù)

          vue中判斷我們寫(xiě)的組件名是不是html內(nèi)置標(biāo)簽的時(shí)候,如果用數(shù)組類(lèi)遍歷那么將要循環(huán)很多次獲取結(jié)果,如果把數(shù)組轉(zhuǎn)為對(duì)象,把標(biāo)簽名設(shè)置為對(duì)象的key,那么不用依次遍歷查找,只需要查找一次就能獲取結(jié)果,提高了查找效率。

          function?makeMap?(str,?expectsLowerCase)?{
          ????//?構(gòu)建閉包集合map
          ????var?map?=?Object.create(null);
          ????var?list?=?str.split(',');
          ????for?(var?i?=?0;?i???????map[list[i]]?=?true;
          ????}
          ????return?expectsLowerCase
          ????????function?(val)?{?return?map[val.toLowerCase()];?}
          ??????:?function?(val)?{?return?map[val];?}
          }
          //?利用閉包,每次判斷是否是內(nèi)置標(biāo)簽只需調(diào)用isHTMLTag
          var?isHTMLTag?=?makeMap('html,body,base,head,link,meta,style,title')
          console.log('res',?isHTMLTag('body'))?//?true

          3. 二維數(shù)組扁平化

          vue中_createElement格式化傳入的children的時(shí)候用到了simpleNormalizeChildren函數(shù),原來(lái)是為了拍平數(shù)組,使二維數(shù)組扁平化,類(lèi)似lodash中的flatten方法。

          //?先看lodash中的flatten
          _.flatten([1,?[2,?[3,?[4]],?5]])
          //?得到結(jié)果為??[1,?2,?[3,?[4]],?5]

          //?vue中
          function?simpleNormalizeChildren?(children)?{
          ??for?(var?i?=?0;?i?????if?(Array.isArray(children[i]))?{
          ??????return?Array.prototype.concat.apply([],?children)
          ????}
          ??}
          ??return?children
          }

          //?es6中?等價(jià)于
          function?simpleNormalizeChildren?(children)?{
          ???return?[].concat(...children)
          }

          4. 方法攔截

          vue中利用Object.defineProperty收集依賴(lài),從而觸發(fā)更新視圖,但是數(shù)組卻無(wú)法監(jiān)測(cè)到數(shù)據(jù)的變化,但是為什么數(shù)組在使用push?pop等方法的時(shí)候可以觸發(fā)頁(yè)面更新呢,那是因?yàn)関ue內(nèi)部攔截了這些方法。

          ?//?重寫(xiě)push等方法,然后再把原型指回原方法
          ??var?ARRAY_METHOD?=?[?'push',?'pop',?'shift',?'unshift',?'reverse',??'sort',?'splice'?];
          ??var?array_methods?=?Object.create(Array.prototype);
          ??ARRAY_METHOD.forEach(method?=>?{
          ????array_methods[method]?=?function?()?{
          ??????//?攔截方法
          ??????console.log('調(diào)用的是攔截的?'?+?method?+?'?方法,進(jìn)行依賴(lài)收集');
          ??????return?Array.prototype[method].apply(this,?arguments);
          ????}
          ??});

          運(yùn)行結(jié)果測(cè)試

          var?arr?=?[1,2,3]
          arr.__proto__?=?array_methods?//?改變arr的原型
          arr.unshift(6)?//?打印結(jié)果:?調(diào)用的是攔截的?unshift?方法,進(jìn)行依賴(lài)收集

          5. 繼承的實(shí)現(xiàn)

          vue中調(diào)用Vue.extend實(shí)例化組件,Vue.extend就是VueComponent構(gòu)造函數(shù),而VueComponent利用Object.create繼承Vue,所以在平常開(kāi)發(fā)中Vue?和?Vue.extend區(qū)別不是很大。這邊主要學(xué)習(xí)用es5原生方法實(shí)現(xiàn)繼承的,當(dāng)然了,es6中 class類(lèi)直接用extends繼承。

          ??//?繼承方法?
          ??function?inheritPrototype(Son,?Father)?{
          ????var?prototype?=?Object.create(Father.prototype)
          ????prototype.constructor?=?Son
          ????//?把Father.prototype賦值給?Son.prototype
          ????Son.prototype?=?prototype
          ??}
          ??function?Father(name)?{
          ????this.name?=?name
          ????this.arr?=?[1,2,3]
          ??}
          ??Father.prototype.getName?=?function()?{
          ????console.log(this.name)
          ??}
          ??function?Son(name,?age)?{
          ????Father.call(this,?name)
          ????this.age?=?age
          ??}
          ??inheritPrototype(Son,?Father)
          ??Son.prototype.getAge?=?function()?{
          ????console.log(this.age)
          ??}

          運(yùn)行結(jié)果測(cè)試

          var?son1?=?new?Son("AAA",?23)
          son1.getName()????????????//AAA
          son1.getAge()?????????????//23
          son1.arr.push(4)??????????
          console.log(son1.arr)?????//1,2,3,4

          var?son2?=?new?Son("BBB",?24)
          son2.getName()????????????//BBB
          son2.getAge()?????????????//24
          console.log(son2.arr)?????//1,2,3

          6. 執(zhí)行一次

          once?方法相對(duì)比較簡(jiǎn)單,直接利用閉包實(shí)現(xiàn)就好了

          function?once?(fn)?{
          ??var?called?=?false;
          ??return?function?()?{
          ????if?(!called)?{
          ??????called?=?true;
          ??????fn.apply(this,?arguments);
          ????}
          ??}
          }

          7. 淺拷貝

          簡(jiǎn)單的深拷貝我們可以用?JSON.stringify()?來(lái)實(shí)現(xiàn),不過(guò)vue源碼中的looseEqual?淺拷貝寫(xiě)的也很有意思,先類(lèi)型判斷再遞歸調(diào)用,總體也不難,學(xué)一下思路。

          function?looseEqual?(a,?b)?{
          ??if?(a?===?b)?{?return?true?}
          ??var?isObjectA?=?isObject(a);
          ??var?isObjectB?=?isObject(b);
          ??if?(isObjectA?&&?isObjectB)?{
          ????try?{
          ??????var?isArrayA?=?Array.isArray(a);
          ??????var?isArrayB?=?Array.isArray(b);
          ??????if?(isArrayA?&&?isArrayB)?{
          ????????return?a.length?===?b.length?&&?a.every(function?(e,?i)?{
          ??????????return?looseEqual(e,?b[i])
          ????????})
          ??????}?else?if?(!isArrayA?&&?!isArrayB)?{
          ????????var?keysA?=?Object.keys(a);
          ????????var?keysB?=?Object.keys(b);
          ????????return?keysA.length?===?keysB.length?&&?keysA.every(function?(key)?{
          ??????????return?looseEqual(a[key],?b[key])
          ????????})
          ??????}?else?{
          ????????/*?istanbul?ignore?next?*/
          ????????return?false
          ??????}
          ????}?catch?(e)?{
          ??????/*?istanbul?ignore?next?*/
          ??????return?false
          ????}
          ??}?else?if?(!isObjectA?&&?!isObjectB)?{
          ????return?String(a)?===?String(b)
          ??}?else?{
          ????return?false
          ??}
          }
          function?isObject?(obj)?{
          ??return?obj?!==?null?&&?typeof?obj?===?'object'
          }

          就先分享這些函數(shù),其他函數(shù),后面繼續(xù)補(bǔ)充,如有不對(duì)歡迎指正,謝謝!

          專(zhuān)注分享當(dāng)下最實(shí)用的前端技術(shù)。關(guān)注前端達(dá)人,與達(dá)人一起學(xué)習(xí)進(jìn)步!

          長(zhǎng)按關(guān)注"前端達(dá)人"

          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  囯产精品久久久久久久久久久久 | 日韩成人一级片 | 亚州操逼 | 久久午夜成人视频 | 看亚洲A级一级毛片 |