0

I don't understand following behaviour of jQuery 1.9.1 in Firefox 22.0, when following code (jsFiddle) does not produce ReferenceError as expected (not even in strict mode), but returns an object instead:

$("#press").click(function(){
    console.log(press);
});

I'd like to read some documentation or explanation for this - is this something useful or should I avoid this? Why it does not overwrite variables inherited from outer scope?

I have no idea what to search for - is there a name for this feature? Or for this kind of objects that are pushed into handler function?

UPDATE - note that object press is a different one from other global objects created from ids - http://jsfiddle.net/Aprillion/BgsZn/2/:

$("html #outer #press").click(function(){
    console.log(output);
    console.log(outer);
    console.log(press);
});

[14:23:02.632] [object HTMLDivElement]
[14:23:02.632] [object HTMLDivElement]
[14:23:02.632] ({jQuery19108414748019423938:2})
Aprillion
  • 21,510
  • 5
  • 55
  • 89
  • See http://stackoverflow.com/questions/3434278 and http://stackoverflow.com/questions/5515659 – LeGEC Aug 06 '13 at 13:21
  • @LeGEC i updated my question to cover a bit different area from answers there, but thanks :) – Aprillion Aug 06 '13 at 13:28
  • The fiddle shows me 3 elements. I'm going to assume you're using IE? – cHao Aug 06 '13 at 13:31
  • @cHao read 1st line of my question again. In IE 10, `press` is equal to other global objects. – Aprillion Aug 06 '13 at 13:33
  • Ah. I haven't used FF in a while. Somehow i don't even have it installed on this machine :P And i'm so used to IE being a bit different... – cHao Aug 06 '13 at 13:35

3 Answers3

2

This is not related to the jQuery, it's related to the fact that some browsers define a global variable for the elements that have ID/name attributes. As you have an element with press ID attribute, press variable refers to that DOM element.

Ram
  • 143,282
  • 16
  • 168
  • 197
  • thank you very much for most of the answer,, however, see my updated question - `press` is different from other global objects somehow.. – Aprillion Aug 06 '13 at 13:27
1

It's common behavior in browsers, when adding an element with an ID attribute to the document, the browser will also show a property in window with the element's ID as the name, and the element as the value. I wouldn't rely on it if compatibility is a concern, as (a) it's not explicitly listed in any common standard i can find, and (b) magic variables can cause all kinds of headaches if you're not careful. But at least 4 of the 5 common browsers currently do it. ( IE, Chrome, Opera, and Firefox all do, though FF's web console is rather flaky about it. I don't have Safari sitting around to test.)

As for why your button is showing up as ({jQuery##########:2}):

When jQuery adds event handlers (or some other types of data) to an element, it sets a property with the name 'jQuery' + the version digits + a big random number, and the value being a unique integer. Something about resources and such.

Anyway, couple that with Firefox's built in console being rather dim-witted. The instant you add a property to an element, the console forgets it's an element. As an example, pop up a console in any existing page (even about:blank will do) and try typing this stuff in order (though you can skip the comments, of course):

d = document.createElement('div')     // [object HTMLDivElement]
d                                     // [object HTMLDivElement]

// all's good so far...
d.id = 'stuff'                        // "stuff"
d                                     // [object HTMLDivElement]

// now set a property the browser doesn't define
d.randomProperty = 42                 // 42
d                                     // ({randomProperty:42})

// still an element, though
d.id                                  // "stuff"

txt = document.createTextNode('test') // [object Text]
d.appendChild(txt)                    // [object Text]
d                                     // ({randomProperty:42})

// and once the property's gone...
delete d.randomProperty               // true
d                                     // [object HTMLDivElement]

The issue is with the console, not with the browser or jQuery. The elements are still elements, and will still work just fine for any elementy stuff you want to do with them.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • thanks for complete answer.. i won't use these global objects and will watch out for funny FF console output,, there is just one downside that if I forget to declare a local variable with the same name, strict mode does not throw ReferenceError.. – Aprillion Aug 07 '13 at 09:26
  • I wonder if something happens with reserved-keyword-like IDs like `for` or `in`? are any global objects created for them? – Aprillion Aug 07 '13 at 15:19
  • Global objects? Quite possibly; you could access them like `window['for']`. Good luck trying to use them without the `window.` though. :) I'd be a bit more concerned about names like `document`, that are already globals. I'd hope the browser's smart enough to avoid trying to set properties that are already defined. – cHao Aug 07 '13 at 16:51
  • Chrome and IE, at least, are smart enough: http://jsfiddle.net/7QP3L/ . And yes, a global object is created for `#for`; you'd access it as `window['for']`. – cHao Aug 07 '13 at 17:00
  • I wasn't afraid about `document` and other global objects, someone would already noticed if they were rewritten :) I'm not going to use these objects from IDs with nor without `window.`, I was just wondering how it works, thanks for the explanation again. – Aprillion Aug 07 '13 at 18:25
0

Does a jQuery selector by id always work without quotes and # sign?

The press variable in your code is not related to the $('#press').click event.

Community
  • 1
  • 1
matth
  • 6,112
  • 4
  • 37
  • 43