動態條件組合的核心在于使用數組存儲條件函數,并通過 every() 或 some() 實現靈活判斷。1. 使用 dynamicif 函數,接收 data、conditions 及 type 參數,type 為 ‘every’ 時需全部滿足,為 ‘some’ 時滿足其一即可;2. 為避免副作用,可在函數內深拷貝 data;3. 對于復雜組合,可用 reduce 統計滿足條件數量,實現“至少滿足 n 個”的邏輯;4. 異步條件下,采用 async/await 結合 promise.all 或 promise.race 處理,確保異步條件正確執行并返回結果。
動態條件組合,說白了,就是讓你的 if 語句更靈活,而不是寫死一堆 && 和 ||。在 JavaScript 里,這事兒其實挺簡單的,但也有一些小技巧可以玩出花來。
直接上解決方案:
核心思路就是把條件放到一個數組里,然后用 Array.prototype.every() 或者 Array.prototype.some() 來判斷。every() 相當于 &&,some() 相當于 ||。
function dynamicIf(data, conditions, type = 'every') { const check = type === 'every' ? conditions.every : conditions.some; return check(condition => condition(data)); } // 示例 const data = { age: 25, city: 'Beijing', vip: true }; const conditions = [ (data) => data.age > 18, (data) => data.city === 'Beijing', (data) => data.vip ]; if (dynamicIf(data, conditions)) { console.log("滿足所有條件"); } if (dynamicIf(data, conditions, 'some')) { console.log("滿足至少一個條件"); }
這個 dynamicIf 函數接收三個參數:data 是你要判斷的數據對象,conditions 是一個包含判斷函數的數組,type 是判斷類型,默認是 ‘every’,表示所有條件都要滿足,也可以設置為 ‘some’,表示只要滿足一個條件即可。
如何避免條件函數的副作用?
條件函數里盡量不要有修改 data 的操作,否則可能導致意想不到的結果。如果確實需要修改,最好在 dynamicIf 函數內部做一個 data 的深拷貝,避免影響原始數據。
function dynamicIf(data, conditions, type = 'every') { // 深拷貝,防止條件函數修改原始數據 const clonedData = JSON.parse(JSON.stringify(data)); const check = type === 'every' ? conditions.every : conditions.some; return check(condition => condition(condition(clonedData))); }
當然,深拷貝也有性能損耗,如果你的數據量很大,可以考慮用其他更高效的深拷貝方法,或者直接避免在條件函數里修改數據。
除了 every 和 some,還有沒有其他更復雜的組合方式?
除了 every 和 some,還可以用 reduce 來實現更復雜的條件組合。比如,你想實現一個“至少滿足兩個條件”的判斷,可以這樣做:
function dynamicIfWithReduce(data, conditions, minCount = 2) { const satisfiedCount = conditions.reduce((count, condition) => { return condition(data) ? count + 1 : count; }, 0); return satisfiedCount >= minCount; } // 示例:至少滿足兩個條件 if (dynamicIfWithReduce(data, conditions, 2)) { console.log("至少滿足兩個條件"); }
這個 dynamicIfWithReduce 函數接收一個 minCount 參數,表示至少需要滿足多少個條件。reduce 函數會遍歷所有條件函數,統計滿足條件的數量,最后判斷是否大于等于 minCount。
如何處理異步條件?
如果你的條件函數是異步的,比如需要調用一個 API 才能判斷,那么就需要用到 async/await 了。
async function dynamicIfAsync(data, conditions, type = 'every') { const check = type === 'every' ? Promise.all : Promise.race; const results = await check(conditions.map(condition => condition(data))); return type === 'every' ? results.every(result => result) : results.some(result => result); } // 示例:異步條件 const asyncConditions = [ async (data) => { // 模擬 API 調用 await new Promise(resolve => setTimeout(resolve, 500)); return data.age > 18; }, async (data) => { // 模擬 API 調用 await new Promise(resolve => setTimeout(resolve, 500)); return data.city === 'Beijing'; } ]; dynamicIfAsync(data, asyncConditions).then(result => { if (result) { console.log("異步條件全部滿足"); } });
這里用到了 Promise.all 和 Promise.race。Promise.all 會等待所有異步條件都完成,然后返回一個包含所有結果的數組。Promise.race 只要有一個異步條件完成,就會立即返回結果。