How do I find where a variable is defined at runtime? - javascript

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):
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):
I can only infer that $ as
function () {
return document.getElementById.apply(document, arguments)
}
must be from the console itself!
Found it.
with strikes again.
Chromium bug for this: http://code.google.com/p/chromium/issues/detail?id=70969

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.

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
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.

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

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">

Related

What is the difference between (function(){/*.....*/})(); and (function($){/*.....*/})(jQuery);

Is there difference between :
(function() {
/*..........*/
})();
and :
(function($) {
/*..........*/
})(jQuery);
Other people explained what the difference is, but not why you use the latter.
The $ variable is most often used by jQuery. If you have one script tag that loads jQuery and another that loads your code, it's perfectly fine. Now throw prototype.js into the mix. If you load prototype.js and then jQuery, $ will still be jQuery. Do it the other way around and now $ is prototype.js.
If you tried to use $ on such a page, you'd likely get errors or weird behavior.
There are many questions on StackOverflow about this problem. Plugins shouldn't assume much about the page they're loaded in, so they use this pattern defensively.
i am asking if there is difference between (function(){/…/})(); and (function($){/…/})(jQuery);
A little difference. In case of (function($){/*…*/})(jQuery); and absense of jQuery you'll get an error message immeditally after page loads. It's a simpler to detect jquery absense or incorrect order of scripts inclusion, when jquery-based code included before jQuery.
In case of (function(){/*…*/})(); you'll get an error message when code inside this construction actually call one of jQuery methods. It's harder to detect this error, but on the other side you can include your jquery-based scripts before jquery.
I prefer first case.
The second form, (function($){/*…*/})(jQuery); can be slightly safer when working in an environment where you don't (or can't) strictly enforce what code gets put on your site.
I used to work on a large site with a lot of third-party ads. These ads would often unsafely inject their own version of jQuery and occasionally they would override jQuery's global $ object. So, depending on how we wrote our code, we might be calling methods that no longer existed or had slightly different behaviour from what we expected. This could be impossible to debug, since some ads would never appear in our area or were excluded from our environment. This meant we had to be extremely protective of scope, inject our dependencies before any ad code had a chance to load, namespace anything that had to be global and pray no ad screwed with us.
Other answers are quite fragmented so I'd like to give a more detailed answer for the question.
The main question can be self-answered if you understand..
What does (function(argument){ /*...*/ })(value); mean?
It's a quick hand version of:
var tempFunction = function(argument){
/* ... */
}
tempFunction(value);
Without having to go through the hassle of conjuring up a new terrible name for a function that you will only call once and forget. Such functions are called anonymous functions since they aren't given a name.
So (function(){/*...*/})() is creating a function that accept no argument and execute it immediately, while (function($){/*...*/})(jQuery) is creating a function that accept one argument named $, and give it the value of jQuery.
Now that we know what the expression means, surely the first think on our mind is
"Why?". Isn't $ jQuery already?
Well, not exactly. We can never be sure. $ is an alias of jQuery, but other libraries can also use the same alias. As user #FakeRainBrigand already pointed out in his answer, prototype.js also use $ as its alias. In such cases, whichever library assigns its value to $ later wins out.
The practice of (function($){...})(jQuery) is very similar to an alias import in other programing languages. You are explicitly telling the system that your function:
Requires an object/library named jQuery, and
Within your function, $ means jQuery.
So even when someone include a new library later that override the alias $ at the global level, your plugin/framework still works as intended.
Because javascript is so... "flexible" in variable assignment, some people (including me) go as far as doing things like
var myApplication = (function($, undefined){ ... })(jQuery);
Apply the same understanding, it is easy to interpret the second argument part as: assign nothing to the variable undefined. So we can be sure that even if some idiot assigned a value to undefined later, our if(checkVariable === undefined){} won't break. (it's not a myth, people really do assign values to undefined)
When is it commonly used in javascript?
This anonymous function practice is most commonly found in the process of providing encapsulation for your plugin/library.
For example:
var jQuery = (function(){
var publicFunction = function(){ /* ... */}
var privateFunction = function(){ /* ... */}
return {
publicFunction : publicFunction
}
})();
With this, only jQuery.publicFunction() is exposed at the global scope, and privateFunction() remains private.
But of course, it is also used any time you simply want to create a function, call it immediately, and throw it away. (For example as a callback for an asynchronous function)
For the bonus question
why they used (function(){}() twice in the below code?
Well, most likely because they don't know what they're doing. I can't think of any reason to put nested function in like that. None at all.
(function(){/*...*/})(); does not set $ as reference to jQuery within IIFE and (function($){/*...*/})(jQuery); sets $ or other parameter name; e.g.; (function(Z){/*...* Z("body") where Z : jQuery*/})(jQuery); as reference to jQuery within IIFE
The they are both closures. The first is just an anonymous function that will fire any well formatted code that is inside immediately. The second is the jQuery closure. It is how the jQuery library initiates it wraps its code in the JQuery object and exposes it isn't the $ symbol.
(function(){}()) // this is a closure
(function($){}(jQuery)) // is a closure that wraps the executed code inside of the jQuery returned object and exposes it via the $.
With this (function(){/*…*/})();, you are not passing any argument to the inner function, while with this (function($){/*…*/})(jQuery); you are passing jQuery as argument to the inner function and expecting its value as $(which means, you will be able to use jQuery inside the inner function).
Ex:
(function($){
$(document).ready(function() {
console.log('all resources loaded');
})
})(jQuery);
They both are examples of Immediately Invoked Function Expression. In that sense, there is no difference between (function(){/*…*/})(); and (function($){/*…*/})(jQuery);. So no benefits are gained by wrapping (function($){/*…*/})(jQuery); inside (function(){/*…*/})();
A new execution context is created when a function is executed. So when (function(){/*…*/})(); is executed a context is created. Again when (function($){/*…*/})(jQuery); is executed, another context is created. Since the first context is not used (i.e. no variables are declared inside it), I don't see any advantages gained by the wrapping.
(function() { // <-- execution context which is not used
(function($) { // <-- another execution context
"use strict";
/*..........*/
})(jQuery);
})();

Newly defined variable reporting "undefined" in functions while the rest are not?

I've had a problem where some of my declared and defined variables have been reported as undeclared when it's time to use them inside a function.
So I've been playing about with it, and it seem like no - whenever I add anymore new variables, they are defined straight after they are defined in code, then inside function blocks they indeed reported undefined.
I have been using resources and not been releasing them, like URL objects and connections to databases, and so wonder if it's because I run out of memory?
So I rebooted my phone - no go. Besides, the older variables defined beneath the newer variable are reporting that they are indeed defined? while the new variable still arn't.
For more clarification, here's what visual studio is reporting:
^Every one of those variable in that block work correctly except for 'newVar' and any other newly defined variables
(disclaimer: I'm not a professional - only a hobbyist, and any code shown does not represent production ready code, thank you!)
Example issue code:
(function() {
"use strict";
var variable1,
variable3 = 10,
variable2 = 100,
function clickHandler() {
console.log(variable1); //prints "undefined" in green text.
console.log(variable2); //prints "100"
console.log(variable3); //prints "'variable3' is undefined" in red text
}
clickHandler();
})();
Developing a Windows Phone 8.1 app using latest public SDK, writing in javascript on Windows 10, inside Visual Studio 2015 community edition.
In reference to my comment, I'll take your response as a "no", the suggested example output is not what you'd get if you actually ran that code - I'll explain why I ask...
What you are referring to is called lexical scoping and it's a core concept - you can reliably access outer variables in a function closure and indeed your example runs without issue - at least on the V8 engine, I'm not in a position to test in a Microsoft flavoured environment right now.
The only notable observation that you could make from it (aside from the typo) would be the use of a function as a statement rather than an expression. See this post on the differences between the two - I've not spent any length of time investigating but it's conceivable that Javascript hoisting order could have quirky behavioural differences across different Javascript engines.
This is probably a red herring though because you'd expect all variables to appear as undefined in such cases - it's easy to verify if this is your issue however by simply swapping out the function declaration:
function clickHandler(){ // ... swap this function statement
var clickHandler = function(){ // ... for this function expression
Now onto what I suspect is actually the problem. I can't see the onPinch function in it's entirety on your screenshot but from what I can see there is no reference to newVar inside of it. The error in your console was not produced by your code but by your attempt to inject a reference to the variable via the debugger, into the execution context after it had been resolved.
When your code is running, the compiler won't just dump everything that was in lexical scope into the local context - it's going to make optimisations, i.e. you can't stick a break-point inside the function and expect to see a parameter that isn't used by the function in your actual code.
If you want to to play around with that variable in the console, make an arbitrary reference to it somewhere - for example, even the following will ensure it's in scope:
function onPinch(ev){
newVar;
//...
}
In your example the var line needs to be terminated with a ;
var variable1,
variable3 = 10,
variable2 = 100;
variable1 will then be the only undefined variable in the clickHandler function.

jQuery - functions moving to window.function

I create a new global object and then put everything in to that new object so it doesn't interfere with anything else anyone else does. After calling the document.ready() function this gets moved to window.bf for unknown reasons. I've reduced this down to a simple example. Anyone have any ideas on what is happening?
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
debugger;
var bf = {}; // Namespace
bf.vars = [];
bf.vars['onclick'] = "";
$(document).ready(function() {
bf.noop = function() {}
bf.noop();
window.bf.noop();
});
</script>
</head>
<body>Test</body>
</html>
So I wind up with two "bf"s. One is the original global object and the second one is the window.bf object. My problem is: Originally, the global object had all of the functions and variables in it. Now the global variable has nothing except bf.vars (an array). Everything else is now in the window.bf object (including everything that was supposed to go in to the global bf.vars array yet I never asked for that to happen.
Up until last Friday (9/25/2015) this did not happen. Now it does.
Update: I just tried removing the document.ready() function. If you remove the document.ready() part - then the global bf object goes back to being a global variable. So this appears to have something to do with jQuery itself.
Before anyone asks: The reason the document.ready() is being used is because some of the functions I define make reference to locations that need to be loaded and jQuery says to use the document.ready() function in order to ensure all elements have been loaded before execution starts. The bf.noop() function is just to give an example of a function and to show that the function no longer shows up in the global bf object.
Screen capture with document.ready():
Screen capture without document.ready():
Better?
In the top-level scope of a script tag, all variables get implicitly attached to window.
The good news is, you actually don't have two bf objects, you only have one with two ways to access it.
var bf = {};
bf.foo = "bar";
document.getElementById('output').innerHTML = JSON.stringify(window.bf, undefined, 4);
<div id="output"></div>
A variable declared outside the scope of a function is bound to the global scope. Since you're declaring var bf = {} inside the script tag, its parent is the window object.
This MDN document is a good read on variables in JavaScript.
Rossipedia has both two good answers as well as leading me to find the problem. See his posts.
For unknown reasons, jQuery version 1.11.1 (I'm using v1.11.3 and thus the 1.11.1|3 in my post) has some kind of an error that was fixed in jQuery version 2.1.3.
But I also found that one of the programs I use to generate the menu for our site was generating an old function name (showIt instead of show_menu) which was causing problems also. By fixing the generated function name the problem has gone away.
This does NOT mean that the jQuery folks can go "Yeah! We don't have to fix anything!" because this is a valid error and the simple code I posted shows how to break jQuery which might mean there is some way to cause real problems with jQuery. So basically, this should be looked at by someone more in tune with jQuery to find out why the code I posted does what it does. Then they can come back and say "You idiot! You did BLAH! and you shouldn't have!" or maybe "Thanks for locating this really obscure problem that no one else in the entire world has come across or cares about." In any event - this is now a known problem. :-)

Removed JavaScript is still executable

If I have the following JavaScript code:
<script id="someJS">
var boom = 'boom';
function example(){
alert(boom);
}
</script>
and then do:
$('#someJS').remove();
I can still call example() even though that JavaScript function is no longer inside the DOM... How can I remove it?
I don't want to null the actual function(s) and variables with: boom = null; example = null; as I don't always know what is inside the JavaScript file. For example the function names, variables, etc. I need to be able to remove the entirity of what was inside that script tag.
Update: For those that wanted to know the user case for this:
Basically in an app I am working on, we have custom JavaScript added for certain clients that when a button is clicked e.g. save, then checks if certain functions exist and then runs them. However because this save button is generic it means that that the custom code gets called all the time after it's added even if it's no longer relevant.
The solution we have come up with (someone had posted this as an answer but they removed it for some reason) was to namespace it all like:
DynamicJS = {
boom: 'boom',
example: function(message) {
alert(message);
}
}
And then we can just do: delete DyanmicJS;
Which removes all the functions and variables inside this namespace from the global scope, effectively binning off what the script file added.
Although I am sure this is not a perfect solution as if you had event listeners inside the file, I'm sure they would still exist!
How can I remove it? I don't want to null the actual function, as I don't always know what is inside the JS file.
You can't. Script code is executed, creates things in the JavaScript environment, and is completely disconnected from the script element that loaded it. Other than completely reloading that environment, if you don't know what the code did, you can't undo it.
Even if you could infer some of what the code did (for instance, by making a list of globals before and after), while you could remove new globals you detected (or at least set them to null or undefined, since delete doesn't work wiith globals added via function declarations or var), that doesn't tell you what event handlers, web workers, etc. the code may have hooked up.
$('#someJS').remove(); only removes the script element from the page.
By the time the element is removed, the script has already been interpreted, which means example has been added to the global scope.
To properly remove that function you could do this:
window.example = null;
However, apparently you don't want to do this, and this will result in a load of errors if there's script elsewhere that actually uses example.
An alternative could be to assign an empty function to it:
window.example = function(){};
This will prevent the "removal" from resulting in errors.
(Aside from the function not returning values when that may be expected)
Once the function has been processed, it is now part of the window's executable list of functions - regardless of if you remove the original source or not.
To remove the function entirely, try:
window['example'] = null;
However, based on your last comment:
I don't want to null the actual function, as I don't always know what is inside the JS file.
It sounds like you want to maintain reference to the function but not have it executable directly? If that's the case, you can store a reference to it and remove the original:
var _exampleBackup = window['example'];
window['example'] = null;
To call it, you can now use:
_exampleBackup();
And to restore it, if you need to:
window['example'] = _exampleBackup;
example();
That function is still in the window.
Code that you put inside a script tag will be ran when the element is created and has no value (roughly) by itself anymore. Removing the tag will not affect the document and the impact it had on it (generally).
To remove the function you need to remove the example property on the window object, which is how the function will be defined, running the code above.
$('#someJS').remove();does nothing more than removing the text from the DOM, but does nothing to the actual function (nor the file), since it is parsed and executed.
In order to delete the function, you could either set it to null or simply overwrite it with example=function(){};
JavaScript Hoisting
There is a concept in JavaScript called Hoisting. In this phase, compiler parse all JavaScript code and declares variables and function at the beginning of scope. In your case, function example and variable boom is already declared and kept in memory. When you run that method, interpreter will call that method and interpret it instead of interpreting actual JavaScript code. You are deleting script block after it went in memory. And thats why it is still executable.
Approaches to do this
1) Use object oriented approach. Add your method in a object, and when you want to delete it, delete that property by using delete.
2) Create one variable which holds a function which contains your code to execute, and set that variable undefined when you want.

Have Firebug break when a global variable x is defined

We have a very large JavaScript application, where after many months of coding there have inevitably sprung a couple scope slip ups where a variable is defined without using the var keyword in the following fashion:
function() {
x = 5; ...
}
instead of:
function() {
var x = 5; ...
}
This is happening somewhere - we're not sure where - and searching for the variable name in question is difficult, since it's a common word that appears 1000s of times in our source.
Is there a way to ask Firebug to break on the line that first creates a given global variable? To clarify, I would like to break at exactly the instant when window.x switches from undefined to a defined value, and to break statement.
I've tried creating a watch expression and hoped I could turn it into a breakpoint, but I can't seem to create watch expressions without some kind of context or scope.
If this isn't possible with Firebug, I'd be interested in anything that can accomplish this in Firefox in general.
Provided a few things
You know the name of the variable
You don't have a variable with that name in the global scope (declared outside functions), but only inside functions.
There are calls to the function that declares the variable.
this little script would do the trick:
<script type="text/javascript">
window.__defineSetter__("x", function(value) { console.trace(); });
x = 1;
</script>
You'll get a trace of the executed code before that assignment.
It may fail to report some situations, so take a look at JSLint. Load all your JS files right there and lint them.
Here's another solution that only works in Firefox because it uses the Firefox-specific watch method.
Put this piece of Javascript at the very top of your html page, just after the <head> tag:
<script>
window.watch('x', function() { debugger });
</script>
Note that watch works on any Javascript object (window is the global Javascript object).
Here's the solution I ended up using by modifying Ionut G. Stan's solution:
window.__defineSetter__("name", function(value) {
if (value=="div") {
debugger;
}
});
I used debugger instead of console.trace(), so I could stop and look at it mid-execution. With console.trace() I got a bazillion trace statements due to this line executing many times.
The leaky scope turned out to be buried in Dojo, where Dojo is setting that variable to the name of a processed element.
View your web page on the SeaMonkey browser (I use version 1.1.16) and look at the error console, you will see a message of this type for each assignment to an undeclared variable :
Warning: assignment to undeclared variable x
Source File: http://....js
Line: ##
In addition to debugging, I would advise to check your code with JSLint, which reports unexpected assignments in the global scope as errors.
There are several command-line bundles of jslint, such as jslint4java which can be used cross-platform in Ant build scripts.

Categories

Resources