74

What is the benefit of angular.isdefined over and above foo === undefined?

I can't immediately think of a benefit.

Ben Aston
  • 45,997
  • 54
  • 176
  • 303
  • 3
    Writing convenience, consistency – devqon Jan 07 '15 at 11:23
  • 2
    You want to use `typeof foo === "undefined"` anyway, in case of handling undefined variables. – theonlygusti Jan 07 '15 at 11:24
  • 1
    @theonlygusti Why does `foo === undefined` not suffice? Windows,frames? – Ben Aston Jan 07 '15 at 11:25
  • 2
    @Ben It will sometimes raise an error, see [this question](http://stackoverflow.com/questions/4725603/variable-undefined-vs-typeof-variable-undefined), and the answers [here](http://stackoverflow.com/questions/27818331/what-is-the-benefit-of-angular-isdefined). – theonlygusti Jan 07 '15 at 11:29
  • Don't forget, in legacy code `undefined` may be redefined – danwellman May 02 '17 at 14:54
  • It has the "benefit" of returning truthy when foo is null as opposed to literally undefined. In short, I actively avoid this construct. – Roboprog Mar 05 '19 at 20:58

4 Answers4

48

Accessing a truly undefined variable in any way in Javascript, except typeof throws an error. You can only use Angular.isDefined with properties. E.g, this would work fine:

angular.isDefined(window.obj);

Because obj is an undefined propery of window.

Examples of the expected behavior:

var foo;
var bar = 42;

typeof foo !== 'undefined'; // false
typeof bar !== 'undefined'; // true
typeof baz !== 'undefined'; // false

angular.isDefined(foo); // false
angular.isDefined(bar); // true
angular.isDefined(baz); // ReferenceError
Alexander Mikhalchenko
  • 4,315
  • 3
  • 28
  • 54
Bharath Kumar Bachina
  • 2,628
  • 3
  • 23
  • 38
  • 1
    it should be `angular.isDefined(window.obj);` using upper case causes reference error – sricks May 26 '15 at 18:43
  • 1
    So in your example, foo is "undefined" since it is declared but not assigned whereas baz is "*truly* undefined" since it wasn't even declared? ... Interesting. – Niko Bellic Sep 23 '15 at 22:37
  • 28
    So, how is this a benefit? :) – Petr Peller Jan 18 '16 at 20:52
  • 1
    Perhaps the supposed benefit is that it's arguably less of a mental strain to ask whether something _is defined_ than to ask if it's _not undefined_. – Jason Swett Sep 21 '16 at 21:42
  • @PetrPeller - its not necessarily a benefit but allows a `truthy` or `falsey` outcome from the evaluation of `that thing that may or may not be` - so its benefit is `its easy to not break things by leaning on this construct` – Brandt Solovij Jun 21 '17 at 17:42
  • @BrandtSolovij Except using `angular.isDefined` will actually break things because ReferenceError is thrown. – Petr Peller Jun 26 '17 at 09:43
  • It would have been more useful to have a function which treats either undefined *OR* null as "not present", but recognizes 0 and/or empty string as "has an actual value" (vs truthy/falsey interpretation of "foo ? 'something' : 'nothing'") – Roboprog Mar 05 '19 at 21:02
28

Here is the source:

function isDefined(value) {return typeof value !== 'undefined';}

Obviously the first reason is a lower verbosity, but it also future proofs angular, especially if the function is used internally.

Matt Way
  • 28,863
  • 10
  • 70
  • 79
17

Like Kamrul said angular does:

function isDefined(value) { return typeof value !== 'undefined'; }

Which means "the type of this var is undefined"... in you example you compare the content of the variable is equals to undefined and angular is checking the type of the variable.

In js the types are dynamic so until you don't assign a value the variable has no type... so isDefined will tell you both, if a variable declaration exist and if this variable has any content.

But, be careful because the variable could be null, in which case the type of the variable would be object.

You could try this code:

var a;
var b = 'asd';
var c = null;

console.log('a: ' + typeof a);
console.log('b: ' + typeof b);
console.log('c: ' + typeof c);
console.log('d: ' + typeof d);

And you will see the next in console:

a: undefined
b: string 
c: object 
d: undefined

So,

a) the var exist but has no value so is undefined

b) the var exist and has value.. this value is a string so this is its type

c) the var exist but is null, the type can't be interfered so its type is object

d) the var has not been declared so... it's undefined

The main point is the diference between "a" and "d"... so try the next:

console.log('a is undefined? ' + a === undefined);
console.log('d is undefined? ' + d === undefined);

You will see the next in console:

false
Uncaught ReferenceError: d is not defined

Which... is a big problem because:

a) tells you that is not undefined when that's not true

d) raise an exception so... you code will fail

Conclusion

Use is defined when you want to check if a variable exists and has been initialized with a value, but be careful with null values because null is an object (so is a defined var).

If you want to validate that a variable exists and has any valid value (so is not null) you can simple do something like:

if (myvar) {
  console.log('myvar is defined and is not null');
} else {
    console.log('myvar is undefined or null');
}

Another good trick is to init to some value if the var is not defined with ||

myvar = myvar || 'some init value';

The above code takes the value of myvar if is defined and not null and if not init it with some value.

As @TonyBrasunas put on his comment if myvar is evaluated to false, 'some init value' will be assigned. Take this into consideration before using this trick.

This is good in functions, for example:

function split(input, charToSplit) {
  charToSplit = charToSplit || ' ';
  return input.split(charToSplit);
}

Then by default you can split with whitespaces: var input = 'asd asd'; var splited = split(input); // --> splited = ['asd', 'asd']

Or... with another char:

var input = 'asd|asd';
var splited = split(input, '|');
// --> splited= ['asd', 'asd']
Carlos Verdes
  • 2,667
  • 17
  • 20
  • 3
    Actually, `myvar = myvar || 'some init value';` will also assign the string value if `myvar` is defined is not null but is falsey. For instance if `myvar` is `false`, your assignment trick here doesn't work predictably. – Tony Brasunas Nov 28 '18 at 05:26
0

I can only guess but I think my guess is a pretty good one.

These two expressions are functionally equivalent:

typeof foo !== 'undefined'

angular.isDefined(foo)

Benefits of the latter include:

1) It's arguably less of a mental strain to ask whether something is defined than to ask if something is not undefined.

2) angular.isDefined(foo) is arguably a lot less "noisy" than typeof foo !== 'undefined', and therefore it's quicker to grasp what's happening.

Note: These aren't my arguments for the superiority of angular.isDefined. What I'm trying to convey is my guess as to why the Angular team wanted to create angular.isDefined and why they thought it was better than the plain JavaScript alternative.

Jason Swett
  • 38,405
  • 60
  • 193
  • 322
  • 2
    They're not functionally equivalent, I'm afraid. In the top case, `foo` can be a name that's not defined in the current scope while in the second case it would throw a ReferenceError. – Gunchars Aug 06 '18 at 18:14