Pergunta

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.

Foi útil?

Solução

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

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top