jashkenas / underscore

JavaScript's utility _ belt
https://underscorejs.org
MIT License
27.33k stars 5.53k forks source link

isNil #2280

Closed jdalton closed 8 years ago

jdalton commented 9 years ago

I recently added an _.isNil method to check for nullish, == null, values after repeated dev requests and figured I'd bing it up here.

It's a pretty common check which makes it a good candidate for inclusion in core. Looking at Underscore's code base there are 27 == null checks compared to 1 === null checks
and 6 === void 0 checks.

akre54 commented 9 years ago

:-1: What's the use case? Just for predicates? Otherwise it's almost universally better to use a language feature than a library function.

jdalton commented 9 years ago

What's the use case? Just for predicates? Otherwise it's almost universally better to use a language feature than a library function.

Well the same could be said about _.isNull or _.isUndefined. I don't see you advocating for their removal.

akre54 commented 9 years ago

Sure. Let's get rid of em.

jdalton commented 9 years ago

Removal of _.isNull or _.isUndefined isn't likely to happen without a major bump and since they're already in core and nullish checks seem to be more broadly appealing than them I think _.isNil is a good addition.

bjmiller commented 9 years ago

I think that a combined function is more useful than the individual _.isNull and _.isUndefined functions. I'm not crazy about the name, though. "Nil" isn't a language concept that exists in JS, and anyone familiar with Ruby might be tempted to think the some of the behavior of nil might somehow be present.

The inverse of this function is already in underscore-contrib, by the name _.isExisty, FWIW. Maybe, _.inNonExisty?

lucasfanning commented 9 years ago

@bjmiller :+1:

jdalton commented 9 years ago

I chose nil because it's similar to CS' existential operator, Goovy's safe-dereference operator, Ruby's nil? function, Python's None and others. See https://en.wikipedia.org/wiki/Null_Object_pattern and search for nil.

JosephClay commented 9 years ago

I find that, when using underscore or lodash as a type checking solution, it's very jarring to encounter == null. There's a context switch that has to happen from an is + Something pattern to double-equals-no!-oh-wait-it's-against-null-we're-okay pattern.

Also very handy for use in predicates. I usually mixin _.exists.

akre54 commented 9 years ago

_.isNil(foo) vs foo == null

!_.isNil(foo) vs foo != null.

I don't see it. _.isUndefined(foo) vs foo === void 0 I get. But that's only really if you're supporting pre-es5 strict mode where undefined could be reassigned or shadowed or you didn't want to do the pass-undefined-as-last-arg-to-iife hack. The vast majority of cases foo === undefined is fine and reads cleaner.

I don't see removal of .isNull or .isUndefined happening without a major bump

You're the one who brought up removing them.

since they're already in core and nullish checks seem to be more broadly appealing

"Consistency" is a pretty lame argument for a feature that won't see much usage.

it's very jarring to encounter == null

This is a language feature. For better or worse you have to get used to seeing it and working with it. Personally I prefer typeof for strings and objects when I can be assured it will work consistently and correctly, and only fallback to _.isFunction or _.isObject for bugs. Get used to learning the language. Use a library for things that are hard to do in the language, don't use it as a crutch.

isExisty or exists is the wrong name because it implies that it guards against a ReferenceError, which of course no function can do. Only the typeof operator works correctly for that.

jdalton commented 9 years ago

You're the one who brought up removing them.

I brought up that you weren't arguing for removal & then you did :P That doesn't invalidate my point. Removal is not likely.

"Consistency" is a pretty lame argument for a feature that won't see much usage.

It stands to reason it could be as popular or more than _.isNull or _.isUndefined. While you've shot down composability it's also a good reason.

isExisty or exists is the wrong name because it implies that it guards against a ReferenceError, which of course no function can do. Only the typeof operator works correctly for that.

I agree. That's why I picked isNil as it's the closest thing I could find to what it is.

jdalton commented 9 years ago

For reference the stats for lodash.isnull and lodash.isundefined impact (direct+indirect dependents) is:

106 unique packages depend on lodash.isnull
125 unique packages depend on lodash.isundefined

The decent showing in the individual module dep count is a good indicator of their popularity.

EvanHahn commented 9 years ago

:+1: for keeping isNull, isUndefined, and isNil. I don't love the name of isNil, but I can't think of something better.

rmkane commented 8 years ago

@jdalton The only name that I think would make the most sense is _.isSet.

A function name of _.nil is a misnomer because, in functional languages e.g. Lisp, a false value will return true for a nil() test.

A Better Approach

See PHP's isset variable handling function:

bool isset ( mixed $var [, mixed $... ] )

     Determine if a variable is set and is not NULL.

Since undefined, in JavaScript, means that the variable has not been set, this sounds like the perfect function name! :ok_hand:

jdalton commented 8 years ago

Set in JavaScript means something else so that would be a bit confusing. I think isNil is fine. It's short & gets the gist across without stepping on an established JS term.

safqwf commented 8 years ago

:-1: == null, === undefined and === null do the job.

theblang commented 5 years ago

I think that == null will trigger many peoples' linting, and checking for both === undefined and === null gets wordy. So _.isNil(value) would be nice.