Bare ID name resolves to actual element -- why?

52 views
Skip to first unread message

Lawrence San

unread,
Jan 1, 2016, 5:42:20 PM1/1/16
to fir...@googlegroups.com
This is such a basic question that it will probably make me look like an idiot, but anyway...

I have an element in my document:

<p id="foo">...

I'm writing a new JS function (in a linked JS file), and sending it a single argument, the ID of an element in the document. My real intention was to send it as a string, but just for the hell of it, I called the function without stringifying or "getting" the element first, just using the bare ID identifier like this:

myNewFunction( foo ) { ...

I thought the function would throw an error ("what's foo?"). But it's not -- the function is receiving it as a complete reference to the actual element. I don't understand this, because I did NOT do any of these:

$(foo)
or
document.getElementById("foo")
or anything like that.

I have no idea what's happening... so in Firebug, I tried just typing into the console:

    foo

And just as in my function, Firebug didn't say "undefined" or throw an error; it returned a reference to the actual element as though I'd typed document.getElementById("foo"). Why?

When I asked Firebug what the typeof foo is, it told me it's an HTML element! How does Firebug know what foo is? I didn't "get" it first!

I tried the same thing in Chrome dev tools, with the same result.

It's hard to figure out what's going on with the function because I'm not sure what the Console convention (Firebug or Chrome) is. Is there some convention that, as a "convenience" to you, if you just type in a bare ID, and run it, the console resolves that to the actual element?

This seems so basic I can't believe I'm confused about this, but I am...

Sebastian Zartner

unread,
Jan 1, 2016, 6:12:18 PM1/1/16
to Firebug
It must have been set by the page. Check the DOM panel to see your variable listed there. You can simply confirm that this variable is unrelated to any devtool by adding an alert(foo) at the first line of your function and not have any devtool open when you're calling it.

To debug where it gets set, set the variable as watch expression and step debug through the code to see when it gets set.

Sebastian

Lawrence San

unread,
Jan 1, 2016, 7:00:33 PM1/1/16
to fir...@googlegroups.com
OK, I'll try that, but there's something else going on. Forget about my function; let's take the simplest possible case. Here's what I just tried:

I created the world's simplest HTML file -- NO JAVASCRIPT AT ALL. Here's the complete code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>trashtest.html</title>
</head>
<body>
<p id="HUH">What is going on?</p>
</body>
</html>

I dragged the file into Firefox, just as a file, _not_ loading it from my development server. Then I opened a Firebug console, and typed in a single word:

    HUH

When I ran it, Firebug's console displayed:

    > HUH
    <p id="HUH">

Firebug displays the element line with syntax coloring, and it's clickable to the HTML tab, including the DOM sub-tab.

Please don't tell me it was "set by the page" -- there's NO JAVASCRIPT ANYWHERE. It's not even running off my Apache server, just off the local (Mac) file system.

Chrome's console gives approximately the same result.

Have browsers/consoles changed recently? Or is this some new HTML5 "convenience" that I haven't heard about? Or maybe I'm just going crazy?

Try pasting the code above into a blank text file, and drag it into your browser. Does your Firebug console not behave the same way?




Simon Lindholm

unread,
Jan 2, 2016, 1:51:45 PM1/2/16
to Firebug
http://www.w3.org/TR/html5/browsers.html#named-access-on-the-window-object

It's a DOM0 thing, and has been there since the beginning of time. If you remember how, back in the days, form fields used to be accessed as "document.formname.inputname.value", this is similar to the magic behind that.

Lawrence San

unread,
Jan 2, 2016, 2:56:08 PM1/2/16
to fir...@googlegroups.com
Ah, interesting. I never noticed that before.

Let me make sure I understand this correctly... the reason we still have to "get" an element -- that is, do document.getElementById("foo") or $(foo) or whatever, when coding JS -- is that the DOM is a feature of the user agent (e.g. a browser engine), not part of the JavaScript language, so we can't rely on that DOM feature for JS coding. Is that right? Apparently there's some overlap; the page you linked to has a short list of "certain Web browser interface elements are exposed in a limited way to scripts" but apparently this isn't one of them.

The question remains, then: If the browser itself (including the Firebug or other Console) may resolve elements from just a bare identifier -- but you can't rely on that -- then how can we trust the console feedback while writing our scripts? How can we be sure that our JS code is successfully "getting" an element if the DOM might be doing it for us?



--
You received this message because you are subscribed to the Google Groups "Firebug" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebug+u...@googlegroups.com.
To post to this group, send email to fir...@googlegroups.com.
Visit this group at https://groups.google.com/group/firebug.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebug/cddba348-2bca-4b4f-adfb-144457b7c239%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


alfonsoml

unread,
Jan 2, 2016, 3:55:07 PM1/2/16
to Firebug
That's due to back compatibility with old scripts for IE. Current browsers provide a compatibility layer so old pages keep on working (it will work also if you try to use document.all).
You can try to use it that way if you like, but then as soon as you try to use any JS lint you'll have lots of warnings due to all the undeclared variables.
Also, you might find that in the future it stops working if you opt to things like strict mode (I'm not stating that it will be that way, only that it's a compatibility hack that shouldn't be needed for correctly written scripts)

Lawrence San

unread,
Jan 2, 2016, 6:57:23 PM1/2/16
to fir...@googlegroups.com
alfonsoml wrote:
You can try to use it that way if you like, but
​...​

​No, I don't want to do that. I have a different concern, almost the opposite of what you said.

I want to use the normal JS approach to "getting" an element. But if my JavaScript is complicated... how can I be sure it's my JS code that's getting the element, rather than this old, unreliable DOM-legacy stuff? I doubt if there's any way I can disable that legacy stuff so I can be sure that my normal JS is actually what's getting the element.


Simon Lindholm

unread,
Jan 2, 2016, 7:06:07 PM1/2/16
to fir...@googlegroups.com
Linting. I hear http://eslint.org/ is good. (You could also strive to avoid IDs in your HTML. Classes are better for most purposes anyway.)
--
You received this message because you are subscribed to a topic in the Google Groups "Firebug" group.
To unsubscribe from this group and all its topics, send an email to firebug+u...@googlegroups.com.
To post to this group, send email to fir...@googlegroups.com.

alfonsoml

unread,
Jan 3, 2016, 2:16:26 PM1/3/16
to Firebug
As I stated in my reply, if you apply a linter like EsLint suggested by Simon you'll get a warning/error on each undeclared variable besides checking your code for many other errors.
Also you can set "use strict" and that will cause also an error (although at runtime) on each undeclared variable.

Lawrence San

unread,
Jan 3, 2016, 4:12:50 PM1/3/16
to fir...@googlegroups.com

Also you can set "use strict" and that will cause also an error (although at runtime) on each undeclared variable.

Thanks... I just read a little about "use strict", which I haven't used before, and tried to use it in this context. It didn't seem to work. Specifically:

First I loaded an HTML file I'm working on, disabled Firebug, and cleared the browser disk and memory caches.

The HTML contains a GIF with the id "masthead"​, like this:

<img id="masthead" src="graphics/masthead.posterFrame.gif">

Nowhere in my code do I turn "masthead" into a variable  -- in fact, I don't try to use it in any JavaScript at all. So now I put a small script at the bottom of the file, just before the </body></html> tags:

<script>
"use strict";
alert( masthead );
</script>

When I reload the page in Firefox, this alert pops up:

       [object HTMLImageElement]

Why doesn't it throw an error, or at least say "undefined"? I tried various things: it makes no difference whether I include "use strict" or not; it makes no difference whether the DTD is HTML5, 4.01 Strict, or 4.01 Transitional.

You said "use strict" only works at runtime. Doesn't an alert qualify as runtime?

Maybe this weird, magical "getting" an element like this, which is the problem I've been wrestling with all along... maybe that doesn't qualify as an "undeclared variable" at all, and therefore doesn't care about "use strict"? After all, if "use strict" is purely a JavaScript thing, but the browser engine's DOM processing (which is independent of JS) is doing this weird stuff, then it might have nothing to do with JS per se... but might still creating a scripting problem (disguising an undeclared variable, making it seem to work but unreliable) or at least make the script harder to analyze as I work on it.

Is there something I don't understand here?


Sebastian Zartner

unread,
Jan 4, 2016, 7:44:42 AM1/4/16
to Firebug
On Saturday, January 2, 2016 at 7:51:45 PM UTC+1, Simon Lindholm wrote:
http://www.w3.org/TR/html5/browsers.html#named-access-on-the-window-object

It's a DOM0 thing, and has been there since the beginning of time. If you remember how, back in the days, form fields used to be accessed as "document.formname.inputname.value", this is similar to the magic behind that.

I have to admit I didn't know about that.


On Sunday, January 3, 2016 at 10:12:50 PM UTC+1, San wrote:

Also you can set "use strict" and that will cause also an error (although at runtime) on each undeclared variable.

Thanks... I just read a little about "use strict", which I haven't used before, and tried to use it in this context. It didn't seem to work.

"use strict"; obviously doesn't influence this behavior. So it looks like linting is the only option to avoid this.

Sebastian
Reply all
Reply to author
Forward
0 new messages