Sorry, I have a weird question; I know undefined is a type in JavaScript; is it possible to set the type of a variable to undefined?
This is a serious question for me although it seems weird.
It can be done in several ways:
Just declare a symbol:
var symbol;
Or declare a symbol and set it to undefined:
var symbol = undefined;
In case the undefined symbol was overridden:
var symbol = void 0;
Or
var symbol = (function(arg) { return arg; })();
Say your variable is named test:
delete test; // true
typeof(test); // "undefined"
This may not work with the strictest of linters or JavaScript runtime environments. This only works if the variable is in the global scope.
Accoding MDN documentation:
The global undefined property represents the primitive value undefined. It is one of JavaScript's primitive types.
Property attributes of undefined
Writable NO
Enumerable NO
Configurable NO
Ways to declare an undefined variable:
var foo;
var bar = undefined;
var baz = void 0;
var undefined = 2; // <= NO
console.log(foo); //undefined
console.log(bar); //undefined
console.log(baz); //undefined
console.log(undefined); //undefined
Mysteriously. Before you could declare the value to undefined, but now I try, and you can not. I guess now it is a reserved word.
Related
Having the code:
foo = {};
foo.bar = 78;
foo.bar.baz = null;
testing foo.bar.baz against null:
if( foo.bar.baz === null )
console.log("foo.bar.baz is null");
else
console.log("foo.bar.baz is NOT null");
results in "foo.bar.baz is NOT null". Why isn't it null since i set it up explicitly?
Because primitives don't have properties, and the value in foo.bar is a primitive.
When you access (get or set) a property on a primitive, the JavaScript engine creates an object for that primitive, sets or retrieves the property value (if any), and then throws away the object. (That's why (42).toString() works; the primitive is promoted to an object backed by Number.prototype, toString is retrieved from that object and called with this referring to the object, and then the object is thrown away.)
So although an object was created in your foo.bar.baz = null statement, and its baz property was set to null, that object was never stored anywhere (certainly not in foo.bar), and so it got thrown away. Later when you do if (foo.bar.baz === null), a new object, which doesn't have the property, is created and you get undefined for its baz property (because it doesn't have one). (Naturally, JavaScript engines can optimize this process to avoid unnecessary object creation.)
We could create a function on Number.prototype that returned the object that gets created, to demonstrate that the object creation really does happen each time you access a property on a primitive:
// Add a `nifty` method to numbers
Object.defineProperty(
Number.prototype,
"nifty",
{
value: function() {
console.log("Number#nifty called");
return this;
}
}
);
var n = 42; // A primitive number
console.log(typeof n); // "number"
var obj1 = n.nifty(); // Creates an object, which we keep
console.log(typeof obj1); // "object"
var obj2 = n.nifty(); // Do it again, and a new object is created
console.log(obj1 === obj2); // false, they're not the same object
If you want to set properties on a number and keep them, you can do that by explicitly creating a Number object:
var n = new Number(42);
n.baz = null;
console.log(n.baz === null); // true
It's rare to want to do that, but it's possible. Just beware that as we showed earlier, two Number objects with the same raw value are not == to each other:
var n1 = new Number(42);
var n2 = new Number(42);
console.log(n1 == n2); // false
console.log(n1 === n2); // false
>, <, >=, and <= will coerce the number back to a primitive and use the raw value, but == and === will not.
Working with numeric value as object in strict mode will run into exception.
By default foo.bar.baz = null will be undefined because foo.bar is not object and .baz will not be set.
This is Your code in strict mode:
'use strict';
var foo = {};
foo.bar = 78;
foo.bar.baz = null;
if(foo.bar.baz === null )
alert("foo.bar.baz is null");
else
alert("foo.bar.baz is NOT null");
here is solution:
'use strict';
var foo = {};
foo.bar = {};
foo.bar.num = 78; // your number here
foo.bar.baz = null;
if( foo.bar.baz === null )
alert("foo.bar.baz is null");
else
alert("foo.bar.baz is NOT null");
p.s. always put 'use strict' inside Your JS files to be able to make JS less versatile.
This is because
foo = {};
foo.bar = 78;
foo.bar.baz = null;
console.log(foo.bar.baz); // undefined
since you are trying to set a property of a number.
foo.bar is a number primitive, not an object. You can't set properties on a number primitive, but you can set properties on a number object.
foo = {};
foo.bar = new Number(78);
foo.bar.baz = null;
Now foo.bar.baz == null.
What is the benefit of angular.isdefined over and above foo === undefined?
I can't immediately think of a benefit.
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
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.
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']
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.
The code below defines a custom method for the Object's prototype that uses the native method "hasOwnProperty" to find the owner of the passed in property.
Object.prototype.findOwnerOfProperty = function(propName){
var currentObject = this;
while (currentObject !==null){
if (currentObject.hasOwnProperty(propName)){
return currentObject;
}
}
}
My encounters with while loops have been usually of this format:
while ( x < 10 ){
// do stuff
x++;
}
Say I called the "findOwnerOfProperty" method on an object:
newObject.findOwnerofProperty(firstProp);
My questions are:
1) What happens to the "this" object while the loop is running?
2) What exactly is the loop iterating through?
3) What is the difference between the first while loop and the second while loop, where the second loop has an obvious increment that explicitly changes the counter 'x' and the first loop doesnt? Which part of the first code changes the "currentObject"?
What is the difference between the first while loop and the second while loop
The first while loop is an infinite loop because currentObject never changes.
Property names are resolved firstly on the object itself, then on the objects on it's [[Prototype]] chain. You can access that chain using Object.getPrototypeOf, so you might be able to do something like:
Object.prototype.findOwnerOfProperty = function(propName) {
var obj = this;
do {
if (obj.hasOwnProperty(propName)) {
return obj;
}
obj = Object.getPrototypeOf(obj);
} while (obj)
}
// Some tests
var obj = {foo:'foo'};
var x = obj.findOwnerOfProperty('foo');
console.log(x == obj); // true
// Find foo on Bar.prototype
function Bar(){}
Bar.prototype.foo = 'foo';
var bar = new Bar();
var p = Object.getPrototypeOf(bar);
console.log(bar.findOwnerOfProperty('foo') == Bar.prototype); // true
// Find toString on Object.prototpye
console.log(bar.findOwnerOfProperty('toString') === Object.prototype); // true
// Non-existant property
console.log(bar.fum); // undefined
console.log(bar.findOwnerOfProperty('fum')); // undefined
The above returns undefined if no such object is found, which seems appropriate given that null is at the end of all [[Prototype]] chains and returning null would suggest that the property was found there.
Note that Object.getPrototypeOf is ES5 so not in all browsers in use.
Edit
It's possible that the function will be called with a value of this that isn't an Object, e.g.:
bar.findOwnerOfProperty.call(null, 'bar');
The desired outcome might be undefined or perhaps a type error, however the actual result depends on whether the code is strict or not and the value provided.
Non–strict code—if this is a primitive, then it will be set to the result of applying the abstract ToObject operator to the primitive value (e.g. if it's a number, then effectively new Number(value), if it's a string, then new String(value)).
In the case of null and undefined, this is set to the global object (note that applying ToObject to null or undefined throws an error) so the wrong inheritance chain will be checked (i.e. the global object, not null) and possibly the global object will be returned.
The fix for both these cases is "RTFM" (well, if there was one…) since by the time any code is executed, this has already been set and it's impossible to check the original call.
Strict code—in this case the value of this is not modified so a check can be made to ensure it's an Object or Function and return undefined otherwise:
Object.prototype.findOwnerOfProperty = function(propName) {
var obj = this;
// Only applies to strict mode
if ((typeof obj != 'object' && typeof obj != 'function') || obj === null) return;
while (obj) {
if (obj.hasOwnProperty(propName)) {
return obj;
}
obj = Object.getPrototypeOf(obj);
}
}
So there may be different results for strict and non–strict mode, e.g.
bar.findOwnerOfProperty.call(7, 'toString');
returns undefined for strict code and Number (i.e. the Number constructor) for non–strict code (because 7 is converted to a Number object as if by new Number(7), and calling typeof on a Number object returns 'object').
To achieve consistency, for values other than null and undefined, the ToObject operator could be emulated for strict code. Alternatively, the non–strict version could operate only on values where typeof returns function or object. I'll leave that decision to anyone who actually wants to implement this in anger.
If I know the variable will be object later, I use:
var obj;
but it doesn't really matter if I initialize it as null or undefined:
var obj = null;
or
var obj = undefined;
For strings I personally use:
var str = '';
as later on I can do
str += 'some text';
and if I use null for example I get "nullsome text".
null, undefined, empty string or 0 are all falsy values so to check if they are defined. which is the correct way to initialize variables if my variable will be used as object, dom node, etc.. ?
It's initialized to undefined by default, just use that, you don't have to write it out:
var obj;
If it you want to concatenate to a string, use '', for counters use 0... Just use common sense.
In an ideal scenario, you'd just declare your variables at the top of the scope like so:
var foo, bar, obj, domNode;
All of these variables will be undefined, as in their value is undefined. If you know for a fact one of these variables will be used as a string in a loop, for example, rather thant writing foo = (foo === undefined ? '' : foo) + 'add this';, just write:
var foo = '', bar, obj, domNode;
If you're going to use the obj var as an object literal, just assign it {my: 'objec', vals: 'here'} when the time comes, or initialize it to {}, and add properties obj.as = 'you'; obj[foo] = 'go';. If you're going to assign a reference to a DOM element, keep it undefined, as any assignment will just generate pointless overhead.
Same goes for any type of reference (function objects, arrays, objects...). Just postpone the assignment, because it'll just overwrite any previous assignment.
As for numbers, undefined + 123 will get evaluate to NaN, so in that case, initializing to 0 makes sense. However, in case of loop counters:
var foo, i, obj, arr = [1,2,3];
for (i=0;i<arr.length;i++)
{
console.log(arr[i]);
}
is equivalent to:
var foo, i= 0, arr = [1,2,3];
for (;i<arr.length;i++)
{
console.log(arr[i]);
}
Only the latter almost looks wantonly complicated. Just use your common sense and you'll be all right.
Just know that variable declarations are hoisted to the top of the scope, but assignments aren't:
console.log(foo);//undefined
var foo = 123;
console.log(foo);//123
because it's translated into:
var foo;
console.log(foo);
foo = 123;
console.log(foo);
So why not write your code as it'll be interpreted by the engine?
What's the difference between the return values of these two expressions...
Expression 1: typeof foo['bar'] !== 'undefined'
Expression 2: 'bar' in foo
... assuming that these conditions are met:
foo is an object,
foo does not contain any properties that have the value undefined set explicitly.
The first tests the value of bar in foo.
The second tests for the existence of the bar property in foo.
var foo = {bar:undefined};
typeof foo['bar'] !== 'undefined'; // false
'bar' in foo; // true
EDIT:
To add some clarification from the comments below, the issue OP is having is that accessing the domConfig property of window.document throws an Error.
This is an issue not related to the typeof operator, but rather to a specific issue with Firefox.
The issue has been documented here as a bug (back in 2003).
A few notable comments from that report:
Zbigniew Braniecki [:gandalf] 2003-11-19 09:09:31 PST
then why it can be iterated with for-in ?
Boris Zbarsky (:bz) 2003-11-19 09:24:05 PST
Because it is defined as a property on the nsIDOM3Document interface. It's
just one that throws if you try to access its getter. ...
Zbigniew Braniecki [:gandalf] 2003-11-19 09:33:53 PST
... So what kind of bug is it?
The goal is to remove not implemented method/property from interface or to
implement it?!?
Boris Zbarsky (:bz) 2003-11-19 09:53:23 PST
The goal is to eventually implement this.
My reading of the spec suggests that they should be the same. The "in" operator semantics are defined in terms of making a call to the internal (conceptual) [[HasProperty]] method, which itself is defined in terms of [[GetProperty]]. When [[HasProperty]] returns "undefined", then the "in" operator results in boolean false; otherwise it's true. Based on the definition of what [[GetProperty]] is supposed to do, that means that an "undefined" result of a property access would have the same meaning.
Given the conditions you outline, there is no difference. Both should produce the same boolean result and should behave the same around prototype lookup.
Object.prototype.hasOwnProperty.call(null, foo, 'bar')
is another common idiom that does the same as those two but does not incude properties available only on the prototype.
var foo = {};
foo.bar = undefined;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
var Con = function() {};
Con.prototype.bar = undefined;
var foo = new Con;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
The in check is simply the same as using a for in loop and returning true if the key is in the for in loop.
[Edit] Didn't see your "don't explicity set it to undefined" condition.
var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"enumerable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
I actaully expected the in test to fail if you set it as non-enumerable. Seems like they are the same.
var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"writable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
Both test still work if the property is "readonly"
var foz = {}
Object.defineProperty(foz, "bar", {
"value": 42
});
var foo = Object.freeze(foz);
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
Freezing the object also doesn't break the tests.
Given those two conditions, the expressions should give you identical results, except if
foo has an EcmaScript 5 getter defined for the bar property. Since the first expression actually reads the property value, that getter will be invoked. The second expression merely checks for the existence of the property so there is no need to incoke any such getter.
you are targeting Internet Explorer 4.0 - the in operator wasn't added until JavaScript 1.4 ;)
Here's some sample code to illustrate the difference in supporting browsers (Chrome, IE9, FF4):
var foo = {};
Object.defineProperty(foo, "bar", {
"get": function () {document.write("Getter invoked!<br/>"); return foo;}
});
document.write('"bar" in foo -->' +
("bar" in foo));
document.write('<br/>');
document.write('typeof foo["bar"] !== "undefined" -->' +
(typeof foo["bar"] !== "undefined"));
document.write('<br/>');
the first one first checks existence of 'bar' key in foo (undefined is returned if it's not found), then checks the type of that key.
the second on checks only existence.