bigdecimal判断等于0_vue2.0源码用到的工具函数,12个简易的复用函数,看看有多简单...
戎馬:https://segmentfault.com/a/1190000019679638
1. 創建一個被凍結的空對象
export const emptyObject = Object.freeze({ })一旦創建不能給這個對象添加任何屬性。
2. 判斷是否是 undefined 或 null
function isUndef (v) { return v === undefined || v === null}在源碼中很多地方會判斷一個值是否被定義,所以這里直接抽象成一個公共函數。
傳入任意值,返回是一個布爾值。
3. 判斷是否不是 undefined 和 null
function isDef (v) { return v !== undefined && v !== null}當傳入的值,既不是 undefined 也不是 null 返回true。
4. 判斷是否是原始類型
function isPrimitive (value) { return ( typeof value === 'string' || typeof value === 'number' || typeof value === 'symbol' || typeof value === 'boolean' )}在js中提供了兩大類數據類型:
5. 判斷是否是對象類型
function isObject (obj: mixed) { return obj !== null && typeof obj === 'object'}傳入的值排除掉 null,因為在js中 null 使用運算符 typeof 得到的值是 object,這是一個 bug。因為歷史原因放棄修復了。
6. 判斷有效的數組下標
function isValidArrayIndex (val) { const n = parseFloat( String(val) ); // 轉成數字 // 下標大于等于0,并且不是小數,并且是有限的數 return n >= 0 && Math.floor(n) === n && isFinite(val)}- 可以傳入任意值,先調用 String 轉成字符串,目的是防止傳入的值為 Symbol 類型,那樣直接調用 parseFloat 會報錯,例如:
原因是在調用 parseFloat 時,內部會調用內置的 ToString 方法。而內置的 ToString 方法在遇到 Symbol類型的值時,會拋出 TypeError 錯誤。
跟使用一些隱式轉換遇到的問題一樣,例如使用 + 號:
let test = '' + Symbol('text');控制臺捕獲錯誤:Uncaught TypeError: Cannot convert a Symbol value to a string都是因為內部會調用內置的 ToString 方法造成的。
而如果手動調用 toString 方法或者調用 String,轉換為字符串,則不會報錯:
let test = Symbol('test');console.log(test.toString()); // "Symbol(test)"console.log(String(test)) // "Symbol(test)"- 接下來判斷 n >= 0 ,數組的下標不能小于0,這樣就會排除掉小于0的數,以及 NaN
- 并且 Math.floor(n) === n 一個數向下取整并且還等于自己,那只能是正整數,排除掉小數,因為數組的下標不能是小數。
- 并且用 isFinite 來判定一個數字是否是有限數
7. 判斷是否是一個 Promise 對象
function isPromise (val) { return ( isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function' )}當一個對象存在 then 方法,并且也存在 catch 方法,可以判定為 Promise 對象。
8. 刪除數組中指定元素
這個方法有效的避免了進行刪除數組某一項時,都要進行查找位置再刪除的重復工作。
function remove (arr, item){ if (arr.length) { const index = arr.indexOf(item) if (index > -1) { return arr.splice(index, 1) } }}- 先判斷數組長度,如果數組是空的,則沒必要進行刪除操作
- 用 indexOf 方法查找到元素在數組中的位置,如果找到返回元素所在的位置下標,如果不存在,則返回-1
- index>-1 代表存在數組中,則調用 splice 進行刪除,并返回刪除的元素組成的數組,也就是 splice 的返回值。
9. 用做緩存的高階函數
用高階函數的好處是無需暴露不同要求的緩存對象在外面,形成一個閉包。下面這個函數的技巧,應用在工作中,可以提高代碼運行的效率。
function cached(fn) { // 創建一個緩存對象 const cache = Object.create(null) return (function cachedFn (str) { // 先從緩存對象中找,要操作的值,是否已經有了操作結果 const hit = cache[str] // 如果有,則直接返回;沒有,則調用函數對值進行操作,并把操作結果存在緩存對象中 return hit || (cache[str] = fn(str)) })}- 調用 cached 時會傳入一個 fn 函數,這個函數對某些值進行操作,操作之后會產生返回值
- 在 cached 函數先定義一個沒有原型的對象,會比用 {} 高效,因為不需要繼承一大堆 Object.prototype 上的屬性。
- 執行完 cached 會返回一個函數 cachedFn,將來接收需要操作的值。函數 cachedFn 內部調用 fn 函數得到操作后的值,并緩存在對象 cache 中,如果再對同一個值進行操作時,則直接從緩存中取,無需再調用函數計算。
例如以下運用,函數的作用是把字符串的首字母大寫。
const capitalize = cached((str) => { return str.charAt(0).toUpperCase() + str.slice(1)})- 先調用 cached 傳入一個函數,這個函數是對字符串進行首字母大寫的操作,并返回首字母大寫的字符串結果,可以說創建了一個計算函數。
- cached 的返回值是函數,也就是上面的 cachedFn 函數。
這時我們就可以調用 capitalize 對字符串進行首字母大寫了。
capitalize('test'); // "Test"capitalize('test'); // "Test"capitalize('test'); // "Test"第一次調用 capitalize 函數,先從緩存對象中取值,沒有,則調用計算函數進行計算結果返回,同時存入緩存對象中。這時的緩存對象為:
{test: 'Test'}再多次調用 capitalize 時,從緩存對象中取值,命中,直接返回,無需再進行計算操作。
10. 遞歸判斷一個對象是否和另個一個對象完全相同
判斷兩個對象是否相同,主要是判斷兩個對象包含的值都是一樣的,如果包含的值依然是個對象,則繼續遞歸調用判斷是否相同。
function isObject (obj){ return obj !== null && typeof obj === 'object'}function looseEqual (a, b) { // 如果是同一個對象,則相同 if (a === b) return true // 判斷是否是對象 const isObjectA = isObject(a) const isObjectB = isObject(b) // 兩者都是對象 if (isObjectA && isObjectB) { try { // 判斷是否是數組 const isArrayA = Array.isArray(a) const isArrayB = Array.isArray(b) // 兩者都是數組 if (isArrayA && isArrayB) { // 長度要一樣,同時每一項都要相同,遞歸調用 return a.length === b.length && a.every((e, i) => { return looseEqual(e, b[i]) }) } else if (a instanceof Date && b instanceof Date) { // 如果都是時間對象,則需要保證時間戳相同 return a.getTime() === b.getTime() } else if (!isArrayA && !isArrayB) { // 兩者都不是數組,則為對象 // 拿到兩者的key值,存入數組 const keysA = Object.keys(a) const keysB = Object.keys(b) // 屬性的個數要一樣,遞歸的判斷每一個值是否相同 return keysA.length === keysB.length && keysA.every(key => { return looseEqual(a[key], b[key]) }) } else { return false } } catch (e) { return false } } else if (!isObjectA && !isObjectB) { // 兩者都不是對象 // 轉成字符串后,值是否一致 return String(a) === String(b) } else { return false }}- 判斷兩個值是否相同,無論是原始類型還是對象類型,如果相同,則直接返回true。
- 如果兩個都會對象,則分為兩種情況,數組和對象。
- 都是數組,則保證長度一致,同時調用 every 函數遞歸調用函數,保證每一項都一樣
- 是時間對象,則保證時間戳相同
- 是對象,則先取出 key 組成的數組,兩者 key 的個數要相同;再遞歸調用比較 value 值是否相同
- 以上都不滿足,直接返回false
- 如果兩者都不是對象,轉成字符串后進行比較。
- 以上都不滿足,直接返回false
例子:
let a1 = [1,2,3,{a:1,b:2,c:[1,2,3]}];let b1 = [1,2,3,{a:1,b:2,c:[1,2,3]}];console.log(looseEqual(a1,b1)); // truelet a2 = [1,2,3,{a:1,b:2,c:[1,2,3,4]}];let b2 = [1,2,3,{a:1,b:2,c:[1,2,3]}];console.log(looseEqual(a2,b2)); // false11. 函數只執行一次
同樣利用高階函數,在閉包內操作標識的真假,來控制執行一次。
function once (fn) { let called = false return function () { if (!called) { called = true fn.apply(this, arguments) } }}- 傳入要執行一次的函數 fn
- 設置標識為 false
- 返回一個函數
實際運用:
function test(){ console.log('我只被執行一次');}let test2 = once(test);test2(); // 我只被執行一次test2();test2();test2();- 調用 once 函數后,會返回一個函數,賦值給 test2
- 第一次調用 test2 后,在函數的尼內部,called 初次為 false, 所以可以執行函數 test,然后把標識 called 設置為true,就類似關閉了大門,下次不再執行。
- 之后在調用 test2 , test 將不再執行。
12. 自定義 bind 函數
function polyfillBind (fn, ctx) { function boundFn (a) { const l = arguments.length return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx) } boundFn._length = fn.length return boundFn}自定義的 bind 函數的場景,都是用來兼容不支持原生 bind 方法的環境。 在自己模擬的 bind 函數中,實際上調用的是 call或 apply。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的bigdecimal判断等于0_vue2.0源码用到的工具函数,12个简易的复用函数,看看有多简单...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每日优鲜app几点更新库存
- 下一篇: js时间选择器_Vuestic Admi