ARTICLE AD BOX
The problem is not with object literals or destructuring — it’s due to prototype inheritance.
All objects in JavaScript already have a toString method via Object.prototype, so this:
function f({ toString, obj1 }) { var existing = toString || obj1; }will almost always treat toString as truthy, even if it was never passed. That’s why you get a false positive.
Correct approach
You need to check whether the property exists on the object itself, not on its prototype. The modern and concise way is:
function f(arg = {}) { if (Object.hasOwn(arg, "toString")) { return arg.toString; } if (Object.hasOwn(arg, "obj1")) { return arg.obj1; } }This avoids the verbosity of hasOwnProperty and correctly ignores inherited properties.
Why other attempts fail
Destructuring ({ toString, obj1 }) reads inherited properties too Default values (= null) only apply when the property is undefined, not when it exists on the prototype Spreading ({ ...arg }) does not remove inherited behavior in this caseRecommendation
Avoid using property names like toString in option objects, since they clash with built-in prototype methods. If you rename it (e.g. stringifyFn), your original destructuring approach will work as expected.
