Suppose I have some variables:
var s = 's', i = 0, o = {}, a = [], n = null, nan = NaN, u;
How can I make any sense of when reading x.p will return undefined, and when it will throw a TypeError?
s.p; // undefined
i.p; // undefined
o.p; // undefined
a.p; // undefined
n.p; // TypeError!
nan.p; // undefined
u.p; // TypeError!
P.S. Are null and undefined the only weird values in this way? Are there others?
Edit
I'm aware that by declaring variables as I have, several of my values have been automatically wrapped by objects (e.g. Number), despite being primitives. Therefore I can treat them like "proper" objects (e.g. {}, []) and attempt to read their properties. But I can't find much explaining what is and isn't wrapped this way.
Yes, null and undefined are the only values that throw an exception when being used in a property access. The dot and bracket property accessors do invoke the internal CheckObjectCoercible function, which is defined as following:
The abstract operation CheckObjectCoercible throws an error if its
argument is a value that cannot be converted to an Object using
ToObject. It is defined by Table 15:
Table 15 — CheckObjectCoercible Results
Argument Type | Result
--------------+------------------
Undefined | Throw a TypeError exception.
Null | Throw a TypeError exception.
Boolean | Return
Number | Return
String | Return
Object | Return
null and undefined being the values that represent Nothing cannot be converted to objects ("wrapped" as you say). Notice that you could of course have an object with an existing property that throws on access, like
var o = {get p() { throw new TypeError("you may not access this"); }};
o.p // TypeError
When you're reading the property of something that's undefined. You're basing saying:
What is undefined of undefined? or in the case of null what is undefined of null ? Neither undefined nor null are objects, therefore you can't set or get properties on/from them. With that in mind, an error will be thrown.
When the object is null/undefined, it'll throw an error because it'll try to access a property of an object that does not exist in first place.
On the other cases, it'll try to access a property of an existing object and will return undefined because the property is not found.
Please note that almost everything in js is an object, as you can see here.
let's firstly start with
why undefined on:
var s='s';
You assigned s to string which is primitive type. Javascript is tricky here in one sense. Though primitive type, when you try to access the property by doing:
s.p
It firstly does this internally:
String(s)
and creates the object and then tries to see if it has that property which is, of course not defined and thus you get undefined. Almost similar things happen with numerical assignment and NAN.
For n=null:
If you do:
var n=null;
typeof n;//"object"
n.p// throws typeerror
In fact,null can be thought of special kind of object without any properties or method to represent absence of value and thus, you get typeerror when you try to access any properties of null.
a.p
o.p
Easily, you can see that you are trying to access the property of an object than is not defined or not built-in and thus it should say, undefined. You should be surprised to see other than that :D.
To add to the other answers here, there is an easy way to check if a property access will throw an exception. Simply loosely compare the value you're unsure of to null, like so:
if(x != null) { // note the LOOSE equality, rather than !==
// do something with x.prop
}
The reason this works is that only null and undefined * throw errors on property access, and they are only loosely equal to each other. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_when_to_use_them.
* There is also a case where some JS objects can apparently "emulate" being undefined, in which case they also are loosely equal to null and undefined.
Related
Asking this question I want to evaluate the following statement true or false:
"There are methods built-in to every data type in JavaScript"
As undefined in data type in JavaScript. I try to find any build-in method for an "undefined" but it appears that it's an only primitive type that does not have one. Or there are some?
let undef = void 0;
console.log(undef.anyPotentialBuildInMethod());
Does any "anyPotentialBuildInMethod()" exists?
Methods are functions that are properties of objects.
Trying to read any property of undefined throws an exception.
undefined has no built-in methods and cannot be assigned any.
const foo = undefined;
console.log(foo.sampleMethod);
While it might appear so, not everything in Javascript is an object. Primitive values (like "foo", 12.34, undefined etc) are not objects and cannot have methods or properties. However, Javascript hides that fact by dynamically boxing (or "coercing") primitive values into objects when you access their properties. So when you do
x = "foo".length
what actually happens is
1. temp = new String("foo") // dynamically coerce a primitive value into an object
2. x = temp.length // get a property of that object
3. destroy temp // delete a temporary object
(Of course, Javascript engines don't actually allocate and then discard these temporary objects, this is just an algorithm defined by the standard, see (1) below).
Two primitive values: null and undefined are exception of this rule: any attempt to coerce them results in a TypeError. So when you do
x = undefined.something
Javascript tries to create a temporary object like in the step 1 above and fails.
The bottom line: null and undefined cannot have properties, because they are primitive values and cannot be converted to objects.
References:
https://262.ecma-international.org/11.0/#sec-getvalue
https://262.ecma-international.org/11.0/#sec-evaluate-property-access-with-identifier-key
https://262.ecma-international.org/11.0/#sec-requireobjectcoercible
No, property access on undefined always throws a TypeError in a standards-compliant engine.
From ECMA-262, 11th Ed., §12.3.2.1:
MemberExpression : MemberExpression [ Expression ]
[…]
Return ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict).
[…]
MemberExpression : MemberExpression . IdentifierName
[…]
Return ? EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict).
In both §12.3.3 and §12.3.4 have:
Let bv be ? RequireObjectCoercible(baseValue).
And in §7.2.1 we have:
The abstract operation RequireObjectCoercible throws an error if argument is a value that cannot be converted to an Object using ToObject. It is defined by Table 15:
Table 15: RequireObjectCoercible Results
Argument Type
Result
Undefined
Throw a TypeError exception.
Null
Throw a TypeError exception.
The only thing that can possibly be considered an exception is the document.all object, which compares loosely-equal (== not ===) to both undefined and null, and returns 'undefined' when passed to the typeof operator, but actually has properties. This is specified in §B.3.7; before the 9th edition of the standard, it was actually contrary to the specification.
I'm not sure of the reason why you are asking this, but, to let you understand better, what you are trying to do is like trying (but not the same) to find an 'x' value so that (0 * x) != 0; 0 is 0 and whethever you use as 'x' you got 0.
And 'undefined' var in javascript is nothing. This is because 'var' doesn't have a type, it can be string, integer, object, function ecc
you can do
var test = "test";
console.log(test);
test = 1;
console.log(test);
and so on, and you'll get no error. var are evauated at execution time, and and undefined var is simply a pointer to nothing so you can't have a function or a property in that
So I know 'null' is a type of 'object'
However, when I do Object.getProtoTypeOf(null) I get an error. Same goes for instanceof, which is kinda the same thing.
If null is a type of Object...it should be in it's prototype chain, right?
// 'object'
typeof null;
// gives error - Cannot convert undefined or null to object
Object.getPrototypeOf(null);
// false ---- why?
null instanceof Object
Is there something I'm missing, or JS is just too hippie ?!
See, null is not an object. It's true that typeof null evaluates to 'object', but it actually came from a limitation and may be considered a quirk - a bug to some extent - of JavaScript. Quoting this article:
The "typeof null" bug is a remnant from the first version of
JavaScript. In this version, values were stored in 32 bit units, which
consisted of a small type tag (1–3 bits) and the actual data of the
value. The type tags were stored in the lower bits of the units. There
were five of them:
000: object. The data is a reference to an object.
1: int. The data is a 31 bit signed integer.
010: double. The data is a reference to a double floating point number.
100: string. The data is a reference to a string.
110: boolean. The data is a boolean.
That is, the lowest bit was either one, then the type tag was only one bit long. Or it was zero, then the type tag was three bits in length, providing two
additional bits, for four types. Two values were special:
undefined (JSVAL_VOID) was the integer −230 (a number outside the integer range).
null (JSVAL_NULL) was the machine code NULL pointer. Or: an object type tag plus a reference that is zero.
It should now be obvious why typeof thought that null was an object: it examined its type tag and the type tag said “object”.
Now, for the rest operations null is treated as a primitive value. That's why, for example, null instanceof Object returns false - any primitive will, as it cannot be an instance. Compare 42 instanceof Number (false) with typeof 42 === 'number'.
For Object.getPrototypeOf(null), it's a bit different. In ES5 standard this function should throw an exception if its argument is a primitive - any primitive:
When the getPrototypeOf function is called with argument O, the
following steps are taken:
If Type(O) is not Object throw a TypeError exception.
Return the value of the [[Prototype]] internal property of O.
However, in ES2015 they changed it:
When the getPrototypeOf function is called with argument O, the
following steps are taken:
Let obj be ToObject(O).
ReturnIfAbrupt(obj).
Return obj.[[GetPrototypeOf]]().
... so Object.getPrototypeOf(42) now works. Yet both Object.getPrototypeOf(undefined) and Object.getPrototypeOf(null) throw the same error:
Uncaught TypeError: Cannot convert undefined or null to object
This exception is thrown by ToObject() method (doc) - and it makes sense, as one cannot 'box' null and undefined. In some ways it's similar to the error you get when trying to access a property of null or undefined.
This question already has answers here:
Does JavaScript have "Short-circuit" evaluation?
(3 answers)
Closed 6 years ago.
Why did javascript not throw a type error when I try to access a property that does not exist?
My code is below
var array = [];
var someBoolean1 = array[0] && array[0].hey;
The value of someBoolean turned out be 'undefinded'; I expect javaScript will throw a type error;
When I do
var array = [];
var someBoolean2 = array[0].hey;
The typeerror is thrown as expected.
But I do not understand why there is no type error in the first block of code.
Any idea?
Because you explicitly guard against the type error...
array[0] && array[0].hey
array[0] is undefined, so:
undefined && array[0].hey
undefined is falsey, so the right hand side is not evaluated, so the result of this expression is the left hand value undefined, which is assigned to someBoolean1.
Tangentially... to make such expressions less repetitive, usually this idiom is used:
var someBoolean1 = (array[0] || {}).hey;
If array[0] is undefined, {} will be used instead, and then the property .hey of that object will be accessed. If array[0] is an object with a property .hey, you'll get its value, otherwise you'll safely get undefined out of the entire expression.
No type error is thrown because your and operator is short circuiting, array[0] is undefined, which is not true, meaning javascript doesn't feel the need to check the second part of your and condition, and doesn't realize that there is a type error.
It happens because of the execution of && expression. array[0] happend to be evaluated to false so the rest of the expression is not evaluated.
if (false && "any another statement is unreachable")
then do something;
second expression not evaluated as array[0] false array[0].hey is not reached
var someBoolean1 = array[0] && array[0].hey;
Short Answer:
Because there is no element at the index 0 of array, and in more generic words, the property 0 is not defined in variable array. Therefore calling a property on something that is not defined would give you an error.
Long Answer:
Consider all JavaScript objects as dictionaries, and lets think that these dictionaries return us the values if we provide the keys that exist in them, otherwise nothing is returned.
Therefore when accessing an object property like myObject.propA (which is same as myObject["propA"]), if it exists in this object then the value of that property is returned and if not then undefined is returned, which denotes that this property is not defined in the myObject.
An array ([]) in JavaScript is also a type of object, and each member in the array is actually the property of that object. So a property in var arr = ["asd", "fgh"] can be accessed by arr[0] or arr["0"], which means that if property 0 of arr exists then it would return the value (in this case "asd"), otherwise would return undefined.
Providing all this, calling a property on something that is undefined is both illogical and illegal, so an exception is raised.
In Javascript i have read that we can define our own value for undefined. Initially undefined == null is true.
After we change the value of undefined will undefined == null still be true?
By assigning our own value to undefined does it mean that we can assign real numbers to it?
Why are there two absence of value thingies like null and undefined? Couldn't we just do with one? Is there any difference between them?
undefined is a variable on the global object which is window in browser environments. Its initial value is the primitive undefined.
Being a property on the global object, historically you could have changed its value as,
window.undefined = "42"; // or just undefined = "42"
The meaning of life is now clearly defined. But since EcmaScript-5 is out, this has been disallowed, and even though it is still a property of the global object, it has been made non-writable now.
The primitives null and undefined are not the same thing if no tampering has occurred.
Null is a data type that has the sole value null. Undefined is another data type whose sole value is the primitive undefined. You can verify whether they represent the same object or not easily.
null === undefined // false
However,
null == undefined // true
is true, because they are both casted to the boolean value false before a comparison is made. The rules for converting both these values to boolean are clearly defined in section 9.2 of the spec.
9.2 ToBoolean
Argument Type | Result
-------------------------------------------------------------------------
Undefined | false
Null | false
Boolean | The result equals the input argument (no conversion).
Number | ..
String | ..
Object | ..
But after we change the value of undefined will undefined == null still be true?
That depends what you change it to. If you change it to null, then yes. If you change it to anything else, then no. Just don't change it.
And by assigning our own value to undefined does it mean that we can assign real numbers to it?
Well, yes. Didn't you try it?
Lastly why are there two absence of value thingies like null and undefined? Couldn't we just do with one? Is there any difference between them?
undefined means that a value has not been assigned or there's no defined value. null means that there is a value, but that value is null. So, yes, there's a difference.
Note that in older JS versions, undefined isn't a keyword the way null is. You can define a value for undefined because it's just a variable.
var null; // syntax error
null = 0; // another error
var undefined; // not an error
undefined = null; //not an error
However, doing this is a bad idea, as it could break things in 3rd party code that you use. ECMAScript 5 defines a read-only undefined property on the global object (note: still not a keyword), so you can't assign to it in ES5 compliant JS implementations.
As for whether undefined == null after assigning a value to null, just like foo == null it depends entirely on the value you assign to undefined.
In javascript undefined means a declared variable but not yet assigned value.
Null is a value so a var = null is a defined variable.
Try to read this What is the difference between null and undefined in JavaScript?
I have been using JavaScript for couple of years and never cared about the difference between null & undefined earlier, I always use undefined to validate the object existence.
But recently I came through this article. Here they said
JavaScript distinguishes between null, which is an object of type 'object' that indicates a deliberate non-value, and undefined, which is an object of type 'undefined' that indicates an uninitialized value — that is, a value hasn't even been assigned yet. We'll talk about variables later, but in JavaScript it is possible to declare a variable without assigning a value to it. If you do this, the variable's type is undefined.
I am completely confused now, what exactly is non-value here. How this non-value differs from undefined. And what are the circumstances javascript returns null.
I have tried the below sample
var sam;
alert(sam); // returns undefined
And
try {
//var sam;
alert(sam);
} catch(ex) { } // exception says: sam is undefined
And I am not sure about when js returning nulls. Can someone clarify me.
alert(sam); // returns undefined
Nope, that's an exception.
You get undefined when you access an unset property; you get an error when you use an unset name directly.
Global variables are interesting because they can be accessed either using a simple variable name, or by using properties of the window global object:
alert(window.sam); // undefined
alert(window['sam']); // undefined
alert('sam' in window); // false
alert(sam); // ERROR
If sam is declared but not initialised, accessing window.sam still gets you undefined, but for a different reason: there is an entry in the window object for sam, but it points to the same undefined object as you get when you access a non-existant property.
var sam;
alert(window.sam); // undefined
alert(window['sam']); // undefined
alert('sam' in window); // ** true
alert(sam); // ** undefined
This is of course a confusing bloody mess; undefined is one of the worst mistakes in the design of the JavaScript language.
null on the other hand is fine and works pretty much the same as null/nil/void/None values in other languages. It doesn't come into any of the above.
<script type="text/javascript">
// variable with an unasigned value
var a;
if (a == undefined) {
alert('a is undefined');
}
if (a == null) {
alert('a is undefined');
}
// this will produce an error
if (b == undefined) {
alert('b is undefined');
}
// this is the right way to handle not defined variables
if (typeof(c) == 'undefined') {
alert('c is blabla');
}
</script>
For a variable to receive a null value it must be assigned. null is used to indicate an unknown or don't care value. undefined on the other hand is designed to indicate that the propery being accessed has never ben assigned a value. This differs from null.
With null one is deliberately saying "I don't know what value this should have yet" or "I don't care what value this is right now". OTH in undefined is really saying "Are you sure you should be using this value it hasn't been assigned".
The way I distinguish them is undefined being "I have not defined this value," and null being "I have defined this value, but I do not know or cannot figure out what the value should be."