[Laszlo-user] The difference between `.` and `[` in Javascript

P T Withington ptw at pobox.com
Fri Jan 16 04:55:01 PST 2009


[Lou, maybe there is a place in the documentation where this could be  
discussed.  I think it may not be well known.]

We recently had a bug report that the debugger started issuing a  
warning in code where it had not before:

   WARNING: reference to undefined property 'length'

The initial fix proposed was to simply change:

   foo.length

to:

   foo.['length']

In Javascript, these two expressions have identical meaning.  The  
second form is normally used if you are trying to access a property  
whose name is stored in a variable.  For instance, to enumerate the  
properties of an object you can say:

   for (var key in myobject) ... myobject[key] ...

But in LZX script, there is one other subtle difference.  When you use  
`.` to access a property, if the property does not exist, you will get  
a warning.  If you use `[` to access that non-existent property, you  
don't.  In either case, the value of the expression will be `undefined`.

We did this because we wanted a way to help users discover type-ohs.   
We wanted to be able to warn users that they were trying to access a  
non-existent property -- perhaps because the spelled the property  
incorrectly, or perhaps because the object they were trying to get the  
property from wasn't the right object.  But we also recognized that  
there were certain cases where the user needed to test if a property  
existed or not, without eliciting a warning.  There needed to be a way  
for the user to say "I know what I am doing".[1]  But, if you do this,  
you really do need to know what you are doing!

As an open source project, OpenLaszlo has lots of people working on  
it, and sometimes, despite the best intentions, one person working on  
the code may not fully understand what another person's code is trying  
to do.  In this case, a well-intentioned change[2] had been mis- 
applied.  A developer who was fixing a dangerous array iteration idiom  
mistakenly applied it to a value that was an object (being used as a  
map or hashtable), not an array.  Hence the warning about no  
'length'.  (They can be forgiven: the code was a doubly-nested loop  
with no comments and variables with names that gave no clue what they  
were being used for.)

If we had taken the simple fix -- silencing the warning by using the  
`[` operator instead of `.` -- the erroneous iteration would have gone  
undetected.  Eventually, someone would have run into a bug that was a  
consequence of masking the iteration bug.  But it might have been much  
harder to find then.

There are several lessons to be learned:

1)  When you get a warning appearing in code that previously worked,  
you _really_ want to understand why that warning started showing up  
all of a sudden.  The simplest way of silencing the warning may not be  
the correct fix.

2)  When working on a piece of code you are unfamiliar with, you  
really need to take the time to understand the code before you make  
changes.

3)  When writing a complex piece of code, use mnemonic names for your  
variables (local names are 'free', you don't make your code smaller or  
faster by using short names), and if it's really tricky code, throw in  
a comment!

---

[1] There are a number of other ways to look at object properties, and  
we used to recommend asking:

   'length' in foo

but in Javascript 2 (and AS3), the `in` operator only applies to  
dynamic properties of an object.  The `in` operator does not work on  
instance properties, e.g.:

   class bar {
     var zot;
   }

   var boo = new bar();

   'zot' in boo => false

   boo.zap = 42

   'zap' in boo => true

So if you need to make a test for the existence of a property that  
might be dynamic or might be an instance property, the only way to  
cover your bases is to use '['.  In the AS3 compiler, you will get an  
error at compile time if you use `.` to access a property that the  
compiler can prove does not exist (because of type inferencing).  So  
the AS3 compiler has adopted the same convention as LZX:  If you use  
'[' to access a property, the compiler assumes you are looking for a  
dynamic property that may or may not exist at runtime, so it will not  
issue a warning.

[2] Lots of people take a shortcut in iterating over an array by saying:

   for (var i in myarray) ... myarray[i] ...

But this is dangerous.  Because Array's in Javascript are also  
Object's, you can add arbitrary properties to an array.  If your loop  
is only supposed to be looping over the numeric indices of the array,  
the above loop will break.  The correct way to iterate over the  
elements of an array is:

   for (var i = 0, len = myarray.length; i < len; i++) ...  
myarray[i] ...













More information about the Laszlo-user mailing list