views:

66

answers:

3

I tested the following code in IE6, IE7 and IE8 with the same result:

<a name="cd"/>a</a>
<script>
try {
cd = new Date;
} catch(e) {
alert(e);
}
</script>

In all cases an error is thrown. However using

var cd = new Date;

seems to solve the problem.
Does anyone know why that is ?

Here is an example: http://jsbin.com/ahuhu4/2

+2  A: 
Pointy
Still doesn't entirely solve the riddle, does it? Why does it work with a `var`? Do try... catch blocks have their own scope? I always thought they didn't
Pekka
@Pekka - the try block doesn't the function does. When you don't use var to declare, the variable automatically scopes to window.variable (global).
Joel Etherton
without the try catch the same differences apply. [var cd = Date] works while [cd = Date] throws an error, so it's not related to the try-catch scope.
vinnybozz
@Pointy - he is not using id for his anchor. He is using name.
Joel Etherton
@Joel Makes sense, but I don't see a function in the example? The code is running in the global context, isn't it?
Pekka
@Pekka - my mistake, I had another script in the brain. The scoping here looks like the var is behaving the same as a "ReDim" would behave in vbscript. It is allowing the already declared object to be redefined within the window context.
Joel Etherton
@Joel - yes, it doesn't have an "id", but IE won't let a little detail like that slow it down.
Pointy
@Pekka: `catch` blocks temporarily add an object to the scope chain. Within the catch block of the following example, there is an object with single property called `e` added to the front of the scope chain: `try { /*...*/ } catch (e) { }`. Don't suppose that's relevant here though.
Tim Down
@Pointy: Using the original code as an example, `cd` certainly exists as a property of `window`. What I imagine IE does is add the element with id `cd` to the global object with the internal `DontEnum` attribute set to `true`, meaning that it won't show up in a `for...in` loop. If you explictly set a property on the global object, it will show up. So in IE, `alert(typeof window.cd);` alerts "object", while the following will only alert for the explicitly set global property `cd2`: `var g = window; g.cd2 = 1; for (var i in g) { if (/^cd/.test(i)) { alert(i + ":" + g[i]); } }`
Tim Down
Oh well that certainly makes sense - I was just looking at the IE debugger's rendering of the window object contents.
Pointy
+2  A: 

When you don't use the var specifier to declare your variable, the variable cd is added as a property to the window object, e.g. window.cd. You already have an object element that is a child of window that is <a name="cd">a</a> which is already typed. You can't specify new Date as a type for this object as it already exists. When you use the var keyword, you are rescoping the variable to a local scope and removing its direct attachment to the window object. This removes the error and allows IE to proceed. Other browser engines handle this differently.

Joel Etherton
Does the name attribute behave like an id in IE ?
vinnybozz
@vinnybozz - It's my understanding (though I haven't looked for a document to back it up) that the name attribute automatically binds an object in the dom to the window object. So putting a div into a page with a name you could call its properties using something like `window.myDiv.innerText'
Joel Etherton
It seems like the var is used to redeclare the cd property to a new type. When I don't declare any cd variable, the window.cd returns the element of that name. By adding [var cd = new Date], now window.cd contains [Wed Oct 13 11:15:00 EDT 2010]. By removing the var and just leaving [cd = new Date] (as in the example), an error is thrown.
vinnybozz
A: 

// Firefox does not automatically define global variables for elements with ids or names. IE including #9, Opera 10, Safari 5 and Chrome 6 all do maintain a global rollcall of named or id'd elements in the document.

It seems like it could crowd up the global namespace...

function a1(id){
    try{
        window[id].style.color= 'red';
    }
    catch(er){
        return er.message+'\n'+'window.'+id+' = '+window[id];
    }
    return 'window.'+id+'='+window[id];
}
function a2(id){
    window[id]= 'red';
    return 'window.'+id+'='+window[id]
}

/*

firefox returns window[idstring] is undefined.

The others all find it, just like the old IE document.all object.

  • query the id as a global identifier:

alert(a1('idstring'))

colors the element red and returns[object HTMLButtonElement] 
(returns [object Object] in older ie browsers)
  • assign the global a new value: alert(a2('idstring')) returns 'red'

  • Try the element again alert(a1('idstring'))

  • throws an error - Cannot convert 'window[id].style' to object

  • or Cannot set property 'color' of undefined or
  • Result of expression 'window[id].style' [undefined] is not an object ot
  • Object expected

*/

kennebec