vue 二维数组_最近研究Vue源码时我发现的一些好玩函数
來源 | segmentfault.com/u/chinamasters
作者 | chinamasters
最近在深入研究vue源碼,把學習過程中,看到的一些好玩的的函數方法收集起來做分享,希望對大家對深入學習js有所幫助。如果大家都能一眼看懂這些函數,說明技術還是不錯的哦。
1. 數據類型判斷
Object.prototype.toString.call()返回的數據格式為 [object Object]類型,然后用slice截取第8位到倒一位,得到結果為 Object
var?_toString?=?Object.prototype.toString;function?toRawType?(value)?{
??return?_toString.call(value).slice(8,?-1)
}
運行結果測試
toRawType({})?//??Object?toRawType([])??//?Array????
toRawType(true)?//?Boolean
toRawType(undefined)?//?Undefined
toRawType(null)?//?Null
toRawType(function(){})?//?Function
2. 利用閉包構造map緩存數據
vue中判斷我們寫的組件名是不是html內置標簽的時候,如果用數組類遍歷那么將要循環很多次獲取結果,如果把數組轉為對象,把標簽名設置為對象的key,那么不用依次遍歷查找,只需要查找一次就能獲取結果,提高了查找效率。
function?makeMap?(str,?expectsLowerCase)?{????//?構建閉包集合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];?}
}
// 利用閉包,每次判斷是否是內置標簽只需調用isHTMLTag
var?isHTMLTag?=?makeMap('html,body,base,head,link,meta,style,title')console.log('res',?isHTMLTag('body'))?//?true
3. 二維數組扁平化
vue中_createElement格式化傳入的children的時候用到了simpleNormalizeChildren函數,原來是為了拍平數組,使二維數組扁平化,類似lodash中的flatten方法。
//?先看lodash中的flatten_.flatten([1,?[2,?[3,?[4]],?5]])
//?得到結果為??[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中?等價于
function?simpleNormalizeChildren?(children)?{
???return?[].concat(...children)
}
4. 方法攔截
vue中利用Object.defineProperty收集依賴,從而觸發更新視圖,但是數組卻無法監測到數據的變化,但是為什么數組在使用push pop等方法的時候可以觸發頁面更新呢,那是因為vue內部攔截了這些方法。
//?重寫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('調用的是攔截的?'?+?method?+?'?方法,進行依賴收集');
?????return?Array.prototype[method].apply(this,?arguments);
???}
?});
運行結果測試
var?arr?=?[1,2,3]arr.__proto__?=?array_methods?//?改變arr的原型
arr.unshift(6)?//?打印結果:?調用的是攔截的?unshift?方法,進行依賴收集
5. 繼承的實現
vue中調用Vue.extend實例化組件,Vue.extend就是VueComponent構造函數,而VueComponent利用Object.create繼承Vue,所以在平常開發中Vue 和 Vue.extend區別不是很大。這邊主要學習用es5原生方法實現繼承的,當然了,es6中 class類直接用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)
??}
運行結果測試
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. 執行一次
once 方法相對比較簡單,直接利用閉包實現就好了
function?once?(fn)?{??var?called?=?false;
??return?function?()?{
????if?(!called)?{
??????called?=?true;
??????fn.apply(this,?arguments);
????}
??}
}
7. 淺拷貝
簡單的深拷貝我們可以用 JSON.stringify() 來實現,不過vue源碼中的looseEqual 淺拷貝寫的也很有意思,先類型判斷再遞歸調用,總體也不難,學一下思路。
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'
}
1.如果看到這里,說明你喜歡這篇文章,請?轉發、點贊、在看同時?標星(置頂)
2.關注公眾號前端人,回復資料包領取我整理的前端進階資料包
3.回復加群,加入前端進階群,和小伙伴一起學習討論!
總結
以上是生活随笔為你收集整理的vue 二维数组_最近研究Vue源码时我发现的一些好玩函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python app服务器_Python
- 下一篇: zookeeper安装包_构建高可用Zo