The two things check slightly different things:
input != null
input != null checks if a value is not null and not undefined. It is exactly the same as checking input !== null && input !== undefined
function notLooselyEqualNull(input) { const result = input != null; return `${input} not loosely equal to null: ${result}`; } console.log(notLooselyEqualNull(null)); console.log(notLooselyEqualNull(undefined)); console.log(notLooselyEqualNull(1)); console.log(notLooselyEqualNull(0)); console.log(notLooselyEqualNull("")); console.log(notLooselyEqualNull("string")); console.log(notLooselyEqualNull(false)); //more examples left as an excercise to the reader
.as-console-wrapper { max-height: 100% !important; }
See for more details on loose equality:
But in this case only null and undefined are loosely equal to each other, therefore != null will return false for either of the two value, true for everything else.
typeof input !== "undefined"
Here the loose vs strict equality does not matter. This expression will check the type of the variable. Since it checks for the type "undefined" it will return
false for the value undefined (since typeof undefined returns "undefined") true for everything else including null
console.log(typeof undefined !== "undefined"); console.log(typeof null !== "undefined");
The typeof check two differences to equality checks
Works with undeclared variables
The typeof check will work with undeclared variables. input == <anything> will read the value of input to use in the comparison. But when attempting to to read an identifier that was never declared with const/let/var, nor as a parameter in a function/method, nor does it exist on the global object, then attempting to read the value throws a ReferenceError:
console.log(input != null);
However, typeof will not throw error in this situation. typeof <any identifier> will return "undefined" for both an undeclared variable or a value that resolves as undefined:
const myConst = undefined; let myLet = undefined; var myVar = undefined; window.myGlobal = undefined; console.log(typeof myConst !== "undefined"); console.log(typeof myLet !== "undefined"); console.log(typeof myVar !== "undefined"); console.log(typeof myGlobal !== "undefined"); console.log(typeof myUndeclared !== "undefined");
.as-console-wrapper { max-height: 100% !important; }
Note
This is exceptionally rarely useful. Under normal circumstances you should not work with something that might be undeclared. This is a huge code smell and suggests you have done something wrong.
Occasionally you might need to run your script on a page not totally controlled by you (e.g., a userscript or inject some code), so you might need to check for the presence of something. But this is very much the exception. If you are controlling your product, then it should be deterministic whether some identifier is there or not.
Under normal circumstances you should not need to use the typeof operator to avoid reading something not yet declared.
It will correctly check the value undefined even if the identifier undefined is overwritten
Due to peculiarity, null is part of the syntax of JavaScript. It cannot be changed in any way, similar to 5 or if and other parts of the core of JavaScript.
However, undefined is not syntax. It is defined as a property of the global object. This makes it possible to change it. In earlier days it was as easy as undefined = 42, so then 42 == undefined would produce true. Nowadays, there are more restrictions but it is still possible in some situations:
function doNotTryThisAtHome(undefined) { //<-- parameter const actualUndefined = void 0; return actualUndefined != undefined; } console.log(doNotTryThisAtHome(42)); // true
However, typeof bypasses whatever undefined is set to (if anything) and directly checks the type of the value you have:
function doNotTryThisAtHome(undefined) { //<-- parameter const actualUndefined = void 0; return typeof actualUndefined !== "undefined"; } console.log(doNotTryThisAtHome(42)); // false
Note
While reading undeclared identifiers might be an extreme edge case, having undefined redefined is even more extreme of an edge case.
There is no need to try and use typeof to check for "true undefined". The reason is that for basically every non-trivial project it would be an extreme problem if undefined resolves to some other value. Throwing a typeof check here and there does not meaningfully mitigate it. Libraries will also likely use undefined checks or even direct assignments somethingNotUsedYet = undefined. Changing the value of undefined will have far reaching consequences and there is no sane way to try and handle this. At that point you are working with insane code and/or in an insane environment.
So, this usage of typeof, while entertaining, is not solving a problem.
Personal recommendation
I use != null for almost all checks. There is very rarely a reason to differentiate. When really needed !== null and !== undefined are still available but more than once being more loose with the check and treating both values the same ends up correct. It is somewhat easy for an undefined to creep in where null is expected, so something like
format number(n) { if (n !== null) return n.toFixed(2); return "0"; }
can suddenly break. This is a real example - some utility code was checking for nulls and it worked for years, but a refactor introduced a code path where n could be undefined in some cases. However, there is no meaningful difference between the two values here, so n != null would never have thrown an error and would have always worked correctly.
Being more strict has a real chance of changing how your code works, without there needing to be a distinction.
Trying to deal with undeclared identifiers should be an extreme outlier. I can probably count on my fingers how often I have used this. And most have been various stages of hacks.
Trying to deal with undefined being redefined has not been needed since the Internet Explorer days. And even then, changing undefined could only happen from extreme sloppiness (dropping random code on your page).
if (null != input)is only "Yoda Speak" to the english speaker (Of one I am ....uuammmmm) so if they equate to the same thing it is really just semantics. IMHO.