12

In the book Javascript the good parts, on the opening page of Ch3 on objects, it states:

An object is a container of properties, where a property has a name and a value. A property name can be any string, including the empty string. A property value can be any Javascript value except for undefined.

Note: undefined is highlighted in the book to denote that is is a literal.

In practice, however, I am able to do it.

var a = { "name": undefined };

What is wrong with my understanding ?

Frankie Ribery
  • 11,933
  • 14
  • 50
  • 64

4 Answers4

8

I believe the answer is that he's wrong.

As you observe, you can set var a = { "name": undefined };.

  • a.name === undefined
  • a.name === a.someFakeProperty

Here's where they're different, though:

  • 'someFakeProperty' in a === false
  • 'name' in a === true

Or, to do it a different way,

  • a.hasOwnProperty('someFakeProperty') === false
  • a.hasOwnProperty('name') === true

Using the somewhat infamous for..in loop,

for (var i in a) {
    alert(i);
}

... will give you name.

So, by value you may not be able to distinguish undefined and undefined, but they are quite different internally.

Addition: he's wrong about the property names, too - a[window] = 43; a[window] == 43; is just fine. Sure, you can't then do a.window, but a.___ is just syntactic sugar for a['___']. As noted in the comments, property names are cast to string so I was wrong about this bit.

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • 3
    He is not wrong about property names, when using the bracket notation, the expression will be converted ToString, property names can be *only strings*, e.g.: `var o = {toString: function () { return 'foo'; }}, a = {}; a[o] = 'test'; alert(a['foo']);` in this example, accessing `a[o]` will convert `o` to string, producing `'foo'` as property name... – Christian C. Salvadó Nov 15 '10 at 04:40
  • Yep. Try `a['[object DOMWindow]'] == 43`. – Ian Henry Nov 15 '10 at 04:45
  • Ah, I see... the string cast didn't occur to me. Answer corrected. – Chris Morgan Nov 15 '10 at 04:53
4

I don't like the terminology that Crockford uses, he seem to mix the concept of undefined and undeclared.

The statement:

A property value can be any Javascript value except for undefined.

Is completely wrong IMO, because undefined is a primitive value of the language.

See also:

Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
2

I think what he's trying to say is that a property's value cannot be undefined because undefined is exactly how JavaScript denotes properties that don't exist. In other words, if you have the following object

var a = { "name": undefined };

Then a.name is undefined, but so is a.someFakeProperty. However, as Ben Lee points out in his comment, name will still show up when you iterate the properties of a using a for loop, while someFakeProperty will not. Therefore, it seems that Crockford was a bit imprecise in conveying the idea in question here.

bcat
  • 8,833
  • 3
  • 35
  • 41
  • 3
    but there is a way to distinguish. If you do `a = { "name": undefined };` and then immediately follow up with `for (att in a) { alert(att); }`, you'll see `name` come up. So internally it is stored as a property of the object, with a value of `undefined`. – Ben Lee Nov 15 '10 at 04:18
  • @Ben: Very interesting! I just tested that in Firefox, and it appears that you are right. Hmm, I wonder what Crockford was trying to say, then... – bcat Nov 15 '10 at 04:20
0

Perhaps this:

var a = {"name": x}; //x is undefined, so it will cause an error.

Just my understanding.

wong2
  • 34,358
  • 48
  • 134
  • 179