12

I've been using jQuery and YUI side-by-side with no issues until recently. Occasionally, inside of a callback for, say, a YUI button, $ will be shadowed by some other function (click for big version): console

and for the life of me, I cannot figure out why this is happening. Yes, I know I could be safe and use jQuery or window.$ everywhere instead of just $, but that's just a workaround and not an actual fix.

At runtime, how can I find where this $ impostor is coming from? - e.g. find where it's declared, and why it's in my bleedin' scope.


It turns out that this behavior is easily reproduced (at least in Chrome and Firefox 4) right here on Stack Overflow, since SO uses jQuery (again, click for full size):

more console still more console

I can only infer that $ as

function () {
    return document.getElementById.apply(document, arguments)
}

must be from the console itself!

Found it.

with strikes again.

enter image description here enter image description here

Chromium bug for this: http://code.google.com/p/chromium/issues/detail?id=70969

m0sa
  • 10,712
  • 4
  • 44
  • 91
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • In the upper right corner of your screen shot - the Search Scripts input box - search for: `return document.getElementById.apply(document, arguments)` – Šime Vidas Feb 12 '11 at 00:56
  • I think the only way to really find out would be to go line-by-line in a debugger, like what Juan suggested, to see where $ is being introduced. If it really is some Chrome problem... it should be fixed ASAP. – vol7ron Feb 12 '11 at 01:57
  • @vol7ron: http://code.google.com/p/chromium/issues/detail?id=70969 – Matt Ball Feb 14 '11 at 19:15
  • wow - this question saved me a _crap-ton_ of time hunting this bug in my own code. Times like these, I love stackoverflow for easily focusing and indexing programming frustrations. Plus one for you, sir. – Matt Apr 14 '11 at 05:18

4 Answers4

2

I'm betting this doesn't happen in IE? This is the only hint I could find:

http://davidwalsh.name/dollar-functions

http://dam5s.tumblr.com/post/3079779011/bug-in-chromes-javascript-console

Some sort of bug in Chrome/Firefox/Safari.

anon
  • 4,578
  • 3
  • 35
  • 54
  • I think you might be right about this - basically, the console is providing its own `$` for me. – Matt Ball Feb 12 '11 at 01:52
  • @Matt: Some consoles do use `$` (for some reason), but I'm pretty sure it is on the global level, so you shouldn't be able to see both jQuery and the other one referenced. If you look in the "Scope Variables" menu, I'd bet that the other `$` is scoped somewhere. – user113716 Feb 12 '11 at 03:01
  • @Matt: Yeah but I still can't see how it would reveal itself at seemingly arbitrary points in your code. Unless `noConflict` is getting called and releasing `$` then recapturing it (or something). – user113716 Feb 12 '11 at 04:20
  • @patrick: it's just variable shadowing caused by the console using `with` when at a break point. – Matt Ball Feb 13 '11 at 22:53
  • @Matt: But is that just represented in the console? I understood your question to mean that console's use of `$` was breaking your code. Did I misunderstand? – user113716 Feb 14 '11 at 19:31
  • @patrick: you're right, it _is_ just represented in the console. This problem was masking another bug that I was trying to debug. You didn't misunderstand what I asked - moreso that I asked the wrong question. – Matt Ball Feb 14 '11 at 20:17
  • @Matt: I think I probably just didn't understand what "shadowing" meant. I've much to learn still. :o) – user113716 Feb 14 '11 at 20:31
2

Here's something to try. Firebug's debugger shows you all the variables that are available at a scope, in your example, it's obviously not local scope, and it's also not global since you already tested window.$. Therefore, it's has(?) to be a closure variable (which should be in the same file).

The attached screenshot shows the closure scopes that are available Firebug debugger

The example shows that data is available within $.each as a closure variable. Again, according to my theory, you should be able to find the culprit by looking for instances of $ on the page, since closures are lexically defined . Maybe there's a self calling function that passes in $ like jquery plugins.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
0

Use a watch expression...

  • Setup a function that checks if $ is correct, maybe jQueryCheck(), and alert if not correct.

    function jQueryCheck(){ if(!$.filter) alert('wtf'); }

  • Add a breakpoint at some step before you expect a problem to occur in the code.

  • Add a watch expression that runs jQueryCheck().

  • Hit breakpoint and just keep clicking on next step. When the variable becomes invalid the alert will pop up and you will then be on the line after the change occurred.

Here is code I used to test

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script>
function invalid(){
    /* set breakpoint on loop below
        click invalid button
        add watch expression jQueryCheck()
        click nextstep repeatedly until wtf alert
    */
    for(var i=0; i<100; i++){
        if(i == 10)
            $ = 10;
    }
}
function valid(){
    $ = jQuery;
}
function jQueryCheck(){
    if(!$.filter)
        alert('wtf');
}
</script>

<input type="button" onclick="valid()" value="run valid">
<input type="button" onclick="invalid()" value="run invaid">
Dan Roberts
  • 4,664
  • 3
  • 34
  • 43
  • 2
    How do you do that? Which variable would you be watching? window.$? $ in the local scope. Also, I don't think there's a way to setup a watch expression that triggers a breakpoint when a variable changes value – Ruan Mendes Feb 12 '11 at 01:00
  • Depends on the tool. Not sure if there are any for JS that allow that but I'll update with an approach in Firebug – Dan Roberts Feb 12 '11 at 01:40
0

you could try using jquery.noConflict http://api.jquery.com/jQuery.noConflict

thescientist
  • 2,906
  • 1
  • 20
  • 15