Javascript函數(shù)技巧學(xué)習(xí)
前言
閱讀代碼是提高編碼水平的好方法,優(yōu)秀的源代碼就像一部文學(xué)巨作,開拓思維,提供啟示。最近在閱讀vue2的源代碼,學(xué)到了很多JS的編碼技巧,后續(xù)陸續(xù)分享出來供參考,順便總結(jié)一下代碼閱讀成果。
1. 緩存函數(shù)
先來看一個(gè)需求,假設(shè)有一個(gè)邏輯復(fù)雜的函數(shù) superComputed
執(zhí)行很費(fèi)時(shí)間,如果每次使用都去計(jì)算一次,就會給用戶帶來很長的等待。這個(gè)時(shí)候需要考慮將計(jì)算結(jié)果緩存起來供后續(xù)程序調(diào)用,緩存函數(shù)需要實(shí)現(xiàn)當(dāng)參數(shù)相同的情況下,直接取緩存結(jié)果。這跟服務(wù)器端為避免過多的查詢數(shù)據(jù)庫而用文件緩存查詢結(jié)果相似,在前端如何實(shí)現(xiàn)呢?
const superComputed = (str) => { // 假設(shè)這個(gè)函數(shù)執(zhí)行時(shí)間很長 console.info("===> 超級計(jì)算開始了……"); return `輸入:${str}`; };
編寫一個(gè) cached
函數(shù)來封裝目標(biāo)函數(shù),這個(gè) cached
函數(shù)接受目標(biāo)函數(shù)作為參數(shù),然后返回一個(gè)封裝好的新函數(shù)。在 cached
函數(shù)的內(nèi)部,可以使用 Object
或 Map
緩存前一個(gè)函數(shù)調(diào)用的結(jié)果。
vue/src/shared/util.js
這個(gè) cached
的代碼如下:
/** * Create a cached version of a pure function. */ export function cached<F: Function>(fn: F): F { const cache = Object.create(null); return (function cachedFn(str: string) { const hit = cache[str]; return hit || (cache[str] = fn(str)); }: any); }
現(xiàn)在將 cached
稍微改下,讓其可以執(zhí)行,每次執(zhí)行 superComputed
函數(shù)都會打印 ===> 超級計(jì)算開始了……
,以方便查看函數(shù)是否被緩存,
如下:
const superComputed = (str) => { // 假設(shè)這個(gè)函數(shù)執(zhí)行時(shí)間很長 console.info("===> 超級計(jì)算開始了……"); return `輸入:${str}`; }; const cached = (fn) => { const cache = Object.create(null); return (str) => { const hit = cache[str]; return hit || (cache[str] = fn(str)); }; }; const cacheSuperComputed = cached(superComputed); console.log(cacheSuperComputed("DevPoint")); console.log(cacheSuperComputed("DevPoint")); console.log(cacheSuperComputed("juejin"));
執(zhí)行后的結(jié)果如下:
===> 超級計(jì)算開始了……
輸入:DevPoint
輸入:DevPoint
===> 超級計(jì)算開始了……
輸入:juejin
從結(jié)果不難看出,函數(shù)執(zhí)行結(jié)果在參數(shù)不變的情況下,取得緩存的數(shù)據(jù)。
2. 將dev-point轉(zhuǎn)換為devPoint
在項(xiàng)目開發(fā)過程中,通常會出現(xiàn)變量風(fēng)格不一致的問題,可以編寫一個(gè)函數(shù)將其轉(zhuǎn)換為統(tǒng)一的風(fēng)格。
vue/src/shared/util.js
/** * Camelize a hyphen-delimited string. */ const camelizeRE = /-(\w)/g export const camelize = cached((str: string): string => { return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') })
將其稍微修改,里面的 cached
函數(shù)就是之前介紹的緩存函數(shù)。
const camelizeRE = /-(\w)/g; const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : "")); }); console.log(camelize("dev-point")); // devPoint
3. 自定義函數(shù)判斷
這里所說的自定義函數(shù),指的是開發(fā)人員自定義的函數(shù),不是Javascript原生宿主函數(shù)??赡芟氲皆砭褪菍⒑瘮?shù)轉(zhuǎn)換為字符串,先來看下結(jié)果:
console.log(cached.toString()); console.log(toString.toString());
執(zhí)行結(jié)果如下:
// 下面是自定義函數(shù)的結(jié)果 (fn) => { const cache = Object.create(null); return (str) => { const hit = cache[str]; return hit || (cache[str] = fn(str)); }; } // 下面是原生宿主函數(shù)的結(jié)果 function toString() { [native code] }
從執(zhí)行結(jié)果來看,原生宿主函數(shù) toString
的結(jié)果始終是 function fnName() { [native code] }
格式,因此就可以通過這個(gè)來區(qū)分,接下來看看VUE項(xiàng)目中的實(shí)現(xiàn)方式。
vue/src/core/util/env.js
在文件的第 58
行,代碼如下:
/* istanbul ignore next */ export function isNative (Ctor: any): boolean { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }
4. JS運(yùn)行環(huán)境
在前端快速發(fā)展的今天, JavaScript 代碼可以在不同的運(yùn)行環(huán)境中執(zhí)行。為了更好的適應(yīng)各種運(yùn)行環(huán)境,需要判斷當(dāng)前代碼是在哪個(gè)運(yùn)行環(huán)境中執(zhí)行的,下面來學(xué)習(xí)一下Vue是如何判斷運(yùn)行環(huán)境的:
vue/src/core/util/env.js
在文件的第 6
行開始,代碼如下:
// Browser environment sniffing export const inBrowser = typeof window !== 'undefined' export const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform export const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase() export const UA = inBrowser && window.navigator.userAgent.toLowerCase() export const isIE = UA && /msie|trident/.test(UA) export const isIE9 = UA && UA.indexOf('msie 9.0') > 0 export const isEdge = UA && UA.indexOf('edge/') > 0 export const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android') export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios') export const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge export const isPhantomJS = UA && /phantomjs/.test(UA) export const isFF = UA && UA.match(/firefox\/(\d+)/)
這些判斷代碼都值得借鑒的,這里不展開介紹了,之前在《4個(gè)值得收藏的Javascript技巧》介紹了瀏覽器的判斷。
到此這篇關(guān)于Javascript函數(shù)技巧學(xué)習(xí)的文章就介紹到這了,更多相關(guān)Javascript技巧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用box固定長寬實(shí)現(xiàn)圖片自動輪播js代碼
這篇文章主要介紹了用box固定長寬實(shí)現(xiàn)圖片自動輪播效果,需要的朋友可以參考下2014-06-06Flow之一個(gè)新的Javascript靜態(tài)類型檢查器
今天我們興奮的發(fā)布了 Flow 的嘗鮮版,一個(gè)新的Javascript靜態(tài)類型檢查器。Flow為Javascript添加了靜態(tài)類型檢查,以提高開發(fā)效率和代碼質(zhì)量,本文給大家分享Flow之一個(gè)新的Javascript靜態(tài)類型檢查器,感興趣的朋友一起學(xué)習(xí)吧2015-12-12JS 組件系列之 bootstrap treegrid 組件封裝過程
最近產(chǎn)品需要設(shè)計(jì)一套相對完整的組織架構(gòu)的解決方案,由于組織架構(gòu)涉及到層級關(guān)系,在表格里面展示層級關(guān)系,自然就要用到所謂的treegrid。下面小編通過本文給大家分享JS 組件系列之 bootstrap treegrid 組件的封裝過程,需要的朋友可以參考下2017-04-04微信小程序Page中data數(shù)據(jù)操作和函數(shù)調(diào)用方法
這篇文章主要介紹了微信小程序Page中data數(shù)據(jù)操作和函數(shù)調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05關(guān)于javascript解決閉包漏洞的一個(gè)問題詳解
閉包在JavaScript高級程序設(shè)計(jì)(第3版)中是這樣描述:閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù),下面這篇文章主要給大家介紹了關(guān)于javascript解決閉包漏洞的一個(gè)問題的相關(guān)資料,需要的朋友可以參考下2022-11-11