-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
inconsistent treatment of null/undefined in _.defaults and _.extend #1565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Related: > _.extend(0, {})
0
> _.extend('', {})
''
> _.extend(NaN, {})
NaN
> _.extend(false, {})
false |
For what it's worth, Backbone tends to use a guard on arguments that may be falsey, e.g. |
This is an anti-pattern, in my view. It's certainly frowned upon in Python, where one often writes if not (x == False or x == None or x == 0 or x == [] or ...): which is almost certainly not the thought one means to express. |
But even an empty object is truthy in javascript. In python an empty dict or list is falsey. If we know we're expecting an Object and not, say, a string (which could be |
The problem is that if we get an unexpected type we may misclassify it. For example, when we receive |
But if you design your API right, you should rarely, if ever, need to do runtime type checking. |
I've always thought of |
So what's the solution, move the guard to inside the diff --git a/underscore.js b/underscore.js
index d25f5ca..8b18dfb 100644
--- a/underscore.js
+++ b/underscore.js
@@ -841,6 +841,7 @@
// Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) {
+ if (obj == null) return {};
_.each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) { |
The way to handle it is like other Underscore methods and not error on So the desired behavior would be: // so with a patch this following would
_.extend(null, {a: 1});
//=> null
// just as this currently does
_.extend(null, {});
// => null |
In the past I've handled if _.extend({}, options, { 'validate': true }); This also has the benefit of not augmenting the passed in |
This also has the benefit of not augmenting the passed in |
But it lets us avoid cloning the object if we don't care about mutating |
Most of the time? Underscore and Lo-Dash guard against it and I try not to augment user provided Introducing your patch muddies the API in much the same way as passing function arguments to The fix to avoid erroring and simply falling through aligns with the rest of the Underscore API without introducing other complications/blurriness. |
I'm interested in reading what @jashkenas and @michaelficarra think of this issue. |
@davidchambers: While I don't particularly like it, @jdalton is right: |
Thanks, Michael. I was actually trying to make a different point with that comment: I was under the impression that a logical false subject was given special treatment. I now realize this is not the case. I'll put together a PR to treat a null/undefined subject the same as any other non-object, as suggested by @jdalton. |
In a pull request on another project, I wrote:
I then realized I needed to add an exception:
Why is this?
The last two inputs above are particularly worrying. The current handling of
_.extend(null, {})
is inconsistent and should be changed. I can think of two options:I favour the latter, as it makes these functions easier to explain. We can then say "null/undefined arguments are treated as empty objects". Also, the functions will then have one return type rather than three (
Object | Null | Undefined
).The text was updated successfully, but these errors were encountered: