Vue 原始碼中一些util函式
JS中很多開源庫都有一個util資料夾,來存放一些常用的函式。這些套路屬於那種常用但是不在ES規範中,同時又不足以單獨為它釋出一個npm模組。所以很多庫都會單獨寫一個工具函式模組。
最進嘗試閱讀vue原始碼,看多很多有意思的函式,在這裡分享一下。
Object.prototype.toString.call(arg) 和 String(arg) 的區別?
上述兩個表示式都是嘗試將一個引數轉化為字串,但是還是有區別的。
String(arg) 會嘗試呼叫 arg.toString() 或者 arg.valueOf(), 所以如果arg或者arg的原型重寫了這兩個方法,Object.prototype.toString.call(arg) 和 String(arg) 的結果就不同
const _toString = Object.prototype.toString var obj = {} obj.toString()// [object Object] _toString.call(obj) // [object Object] obj.toString = () => '111' obj.toString()// 111 _toString.call(obj) // [object Object] /hello/.toString() // /hello/ _toString.call(/hello/) // [object RegExp] 複製程式碼

上圖是ES2018的截圖,我們可以知道Object.prototype.toString的規則,而且有一個規律,Object.prototype.toString的返回值總是 [object
+ tag
+ ]
,如果我們只想要中間的tag,不要兩邊煩人的補充字元,我們可以
function toRawType (value) { return _toString.call(value).slice(8, -1) } toRawType(null) // "Null" toRawType(/sdfsd/) //"RegExp" 複製程式碼
雖然看起來挺簡單的,但是很難自發的領悟到這種寫法,有木有。。
快取函式計算結果
假如有這樣的一個函式
function computed(str) { // 假設中間的計算非常耗時 console.log('2000s have passed') return 'a result' } 複製程式碼
我們希望將一些運算結果快取起來,第二次呼叫的時候直接讀取快取中的內容,我們可以怎麼做呢?
function cached(fn){ const cache = Object.create(null) return function cachedFn (str) { if ( !cache[str] ) { cache[str] = fn(str) } return cache[str] } } var cachedComputed = cached(computed) cachedComputed('ss') // 列印2000s have passed cachedComputed('ss') // 不再列印 複製程式碼
將 hello-world
風格的轉化為 helloWorld
風格
const camelizeRE = /-(\w)/g const camelize = cached((str) => { return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') }) camelize('hello-world') // "helloWorld" 複製程式碼
判斷JS執行環境
const inBrowser = typeof window !== 'undefined' const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase() const UA = inBrowser && window.navigator.userAgent.toLowerCase() const isIE = UA && /msie|trident/.test(UA) const isIE9 = UA && UA.indexOf('msie 9.0') > 0 const isEdge = UA && UA.indexOf('edge/') > 0 const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android') const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios') const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge const isPhantomJS = UA && /phantomjs/.test(UA) const isFF = UA && UA.match(/firefox\/(\d+)/) 複製程式碼
判斷一個函式是宿主環境提供的還是使用者自定義的
console.log.toString() // "function log() { [native code] }" function fn(){} fn.toString() // "function fn(){}" // 所以 function isNative (Ctor){ return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) } 複製程式碼