When working with JavaScript, we often need to set default configurations and allow users to override certain values. A common but flawed approach is using the logical OR (||
) operator for defaults, which can lead to unexpected behavior. This article explains why ||
is problematic for object merging and how to correctly override defaults using the ES6 spread operator (...
).
1. The Problem: Why ||
Falls Short
Consider this typical pattern:
const enabledEngines = this.settings?.enabledEngines || {
baidu: true,
google: true,
bing: true,
so: true,
sogou: true
};
Key Issues with ||
:
-
||
Only Checks for Falsy Values, Failing to Overridefalse
- If
this.settings?.enabledEngines
is{ google: false }
, the||
operator won’t apply the fallback (since an object is truthy), incorrectly keepinggoogle: true
. - The fallback only triggers if the left side is
undefined
/null
.
- If
-
No Partial Overrides
- If a user only wants to disable one engine (e.g.,
{ bing: false }
),||
forces a full replacement, discarding other defaults.
- If a user only wants to disable one engine (e.g.,
2. The Solution: Object Spread Operator (...
)
The correct approach is to let user settings override defaults without discarding the entire object. The ES6 spread operator (...
) solves this elegantly:
const enabledEngines = {
baidu: true,
google: true,
bing: true,
so: true,
sogou: true,
...this.settings?.enabledEngines // User settings override defaults
};
Why This Works:
- Correctly Handles
false
Overrides- If the user passes
{ google: false }
,google
is properly disabled while other defaults remain.
- If the user passes
- Supports Partial Updates
- Users only need to specify changes; unspecified keys keep their defaults.
- Safer Than
||
- Even an empty object
{}
won’t trigger an unwanted fallback.
- Even an empty object
3. Real-World Examples
Case 1: User Disables Google
const userSettings = { google: false };
// Wrong (||)
const badResult = userSettings || { google: true, bing: true };
// => { google: false } ( bing is lost!)
// Right (...)
const goodResult = { google: true, bing: true, ...userSettings };
// => { google: false, bing: true } (Correct!)
Case 2: No User Settings Provided
const userSettings = undefined;
// Wrong (||)
const badResult = userSettings || { google: true };
// => { google: true } (Works but inflexible)
// Right (...)
const goodResult = { google: true, ...userSettings };
// => { google: true } (Same outcome, but consistent)
4. When Is ||
Acceptable?
While ||
isn’t ideal for objects, it’s still useful for:
- Primitive defaults (e.g.,
string
,number
,boolean
)const limit = userLimit || 10; // Fails if userLimit is 0!
- Full replacements (not merging)
const config = userConfig || defaultConfig; // Replaces entirely
For object merging, always prefer ...
.
微信赞赏
支付宝赞赏