I saw many code that began like that
var a=a||{};
Now I know that its check if a exist.
My question is why to check it if its at the first of the code?
I mean the programmer know that a is not exist.
The programmer should know if the variable exists or not.
It's used to mash different pieces of script together without having to keep track of which part of the script is loaded first. Several scripts will have the same piece of code at the start, so they share the same variable.
For the first script, the variable is declared, and there is no previous value for it, so the {} value is used.
For the following scripts that use it, the var is ignored as the variable is already declared, and the previously set value of the variable is used.
Of course, declaring the same variable in several places has a code smell to it. Preferrably you should keep track of what you are doing so that you only declare it once.
Translated into clearer code
var a; // The variable declaration gets brought up because of hoisting
More info on hoisting here
if( a ) {
a = a; // if a is a truthy value then assign it to itself
} else {
a = {}; // if a is a falsy value then set the default to an empty object
}
Hope that helps
That's a shortcut to fall back on a default value - {} in this case.
Basically, javascript can be written in multiple files and within each file you can have multiple declarations and functions defined.
Even if the programmer knows for a given instance if the variable exists or not, there is no way to know if it already exists when this code is called from somewhere else.
This should not happen in well written code (all from one developer / house) but it does happen in projects where the js code is amalgumated from multiple places.
This SO question has a very nice answer about variable scopes in javascript, it should clarify your doubts.
Related
There are similar questions here but they didn't really answer my questions.
So I am curious why we can't declare the same variable twice in Java?
for example:
int a = 4;
int a = 6;
this won't really work in Java.
However in javascript, this actually works:
var a = 1;
var a = 2;
In javascript, people said that the declaration immediately got moved to the start so that it became like this:
var a;
a = 1;
a = 2;
The simple, obvious answer is because the compiler doesn't let you. But now let's go a step further - why would this be desired?
The reason here is that declaring a variable twice is a sign of a mistake. It usually means one of three things:
Your variable names are not specific enough. Perhaps you used int length twice and it barks at you. You probably should make your name more specific to what it holds the length of, for example int originalLength and int extendedLength when copying an array or something.
Your method is too long. Why is your method so long that you need two of the same variable? Chances are you're duplicating code, so consolidate that into a method.
You haven't really thought out your method. This is sort of an extension of number 2, but the truth is you should decide what a method does before you write it. If you're adding a variable that already exists, it probably means that you haven't decided exactly what this method is doing.
Each of those is a major code smell, and is probably the source of bugs down the road. (And not far down the road!) In each of the cases, allowing you to declare a variable twice is going to cause ambiguity that would have been prevented if it stopped you from compiling.
Now, does this mean there aren't cases where it might be nice? Sure. There might be. Maybe you've covered all your bases and you're absolutely sure it's okay to reuse that variable. In that case, just reassign it instead of redeclaring it. Personally, I'd advise against that, but it's your foot to shoot if you want to. :)
You can use the same variable name if the scopes don't overlap, for instance i could have a variable in a private method called "var1" and then in another method have the same thing, these two would not conflict
However since everytime i use "int var1" in the same scope, java is re-declaring the variable, it wont allow it, as it's a conflicting variable name, whereas in java script the declaration happens once, as it's weakly typed
now it has been rectified or improvised in javascript too with the new let keyword
if you try to intialize the same variable name more than once it will throw an error
let a = 4;
let a = 5;
will throw an error in ES6
I noticed that Google Closure Compiler did not rename document to something like d to reduce space.
I cannot think of a case where this would break the code (ie where document points to something else down the road). Actually the same goes for window.
Is there a reason for protecting document this way?
== EDIT ==
By renaming it I was thinking reassigning it. Example below.
var d=document;
var obj1=d.getElementById("obj1");
var obj2=d.getElementById("obj2");
... // with enough uses of document so it makes to reassign it size-wise.
Closure-compiler does not perform this "optimization" by default for the simple reason that it produces LARGER source when used with gzip. You can enable this optimization by turning on the AliasExternals pass using either the Java API or a custom build.
See https://code.google.com/p/closure-compiler/source/browse/src/com/google/javascript/jscomp/AliasExternals.java#38
What happens?
ProblemFactory's guess is correct.
This is a //TODO in the closure compiler source code. If we didn't preserve document and window and instead ran them over with d for example, at the moment the closure compiler does not know if it's overriding a global from another file. Like the comments say this will be resolved in the future at which point.
Enough words, show me the source!
If we check the closure compiler source code inside VariableReferenceCheck.java we can find the following:
private class ReferenceCheckingBehavior implements Behavior {
#Override
public void afterExitScope(NodeTraversal t, ReferenceMap referenceMap) {
// TODO(bashir) In hot-swap version this means that for global scope we
// only go through all global variables accessed in the modified file not
// all global variables. This should be fixed.
// Check all vars after finishing a scope
for (Iterator<Var> it = t.getScope().getVars(); it.hasNext();) {
Var v = it.next();
checkVar(v, referenceMap.getReferences(v).references);
}
}
If we check the hot-swap algorithm itself we can see that:
// Note we use the global scope to prevent wrong "undefined-var errors" on
// variables that are defined in other JS files.
So, we can see that this is just the closure compiler not understanding the code of globals across multiple files well enough to make that replacement. You can always do the replacement yourself :)
I think document is standardized, always-global variable. To use the same way d it has to be global also, thus global namespace will have another "junk" variable.
It could be dangerous for not aware developers (which wont be aware of that thus it is not standard variable).
I'm trying to tidy up some javascript code and one of the steps is removing all useless (or plain wrong) global variables that have slipped in from errors like:
for (prop in obj) { ...
instead of
for (var prop in obj) { ...
JSLint helps a bit in finding out this nastiness, but it is not 100% foolproof when the nastiness happens at runtime.
I already tried to add some monitoring code that routinely checks the global scope logging to the console if some new variable is detected, and that helped some more, but when it tells me that a new global variable named "i" has been detected ... well, it's a mess finding out where that happened in thousands of lines of code.
So here we come: is there a better way/tool/script/whatever to find the little pests?
My dream is something like a Firebug plugin that stops the execution whenever a new global variable is created...
Thanks!
You may find this bookmarklet useful.
Also, checkout this answer: How to detect creation of new global variables?
You can now intercept variable definition as explained on this similar question
window.__defineSetter__('sneakyVariable', function() {
debugger
})
and you'll be able to find where it was defined
I wonder if you could set a timeout to create a list of all global variables and then compare that against the last time the timeout fired. I found this on Stack Overflow, and maybe you could use this code in conjunction with a setTimeout() to get what you want.
Blockquote
Yes and no. "No" in almost every situation. "Yes," but only in a limited manner, if you want to check the global scope. Take the following example:
var a = 1, b = 2, c = 3;
for ( var i in window ) {
console.log(i, typeof window[i], window[i]);
}
Stack Overflow link: Getting All Variables In Scope
well, I wrote this long time ago, so code sucks, but it does the job: https://gist.github.com/1132193
paste in the firebug console or include as a script.
You say, you are trying to tidy up some code.
In that case - use IDE, like NetBeans PHP (free) or JetBrains WebStorm (30$). They both color global variables, and do lots of other useful stuff ;)
If your polling script will still detect creation of global variables - trace down offending functions, and make them suffer ;) Eventually, the code will become clean.
I'm trying to get 2 scripts to run on the same page but they won't play nice with each other. One is called TabTop http://www.isdntek.com/tagbot/tabtop.htm and the other is Clic*Pic http://www.isdntek.com/tagbot/gallery.htm, both by isdntek. I can get either one of them to run fine all by themselves, but not both together. I looked around and tried to find the answer to this problem by myself, but to no avail.
I would greatly appreciate any help that can be provided.
Thanks!
You can wrap each script in a self calling function:
(function(){
//As long as you don't use global variables
//the content here is protected from any interaction with the outside
})();
Now, if both codes use global variables, the task will be unfortunately harder.
The RainbowCodeModule6.js file is used by both pages, it sets a very large number of global variables (quite a few because it doesn't declare local variables within functions), so it is quite possible that with two scripts trying to use the same set of globals, they are getting conflicts. e.g. (my wrapping for posting here)
function changeShades(color){ //--update the vertical column of light/dark shades
var ymax=paletteymax
if (!color){return}
for (i=0; i<ymax; i++){
document.getElementById('colorShades'+i).
style.backgroundColor=colorBrightness(color,(ymax-1-i)/(ymax-1))
}
}
The above doesn't keep it's counter i local and depends on the global paletteymax. I can't say if that's your problem, but it is indicative of poor programming and application architecture. Another example:
function dec2hex(R,G,B) { //--Converts three R-G-B components to
// a single internet hex color
var hexTest="0123456789ABCDEF";
Rd_hi=R/16; Rd_lo=R%16;
Rd=hexTest.substr(Rd_hi,1)+hexTest.substr(Rd_lo,1)
Gn_hi=G/16; Gn_lo=G%16;
Gn=hexTest.substr(Gn_hi,1)+hexTest.substr(Gn_lo,1)
Bu_hi=B/16; Bu_lo=B%16;
Bu=hexTest.substr(Bu_hi,1)+hexTest.substr(Bu_lo,1)
hexval='#'+Rd+Gn+Bu
return hexval;
}
Why they decided to keep hexTest local but let all the other variables go global is beyond me. Variables R, G and B are also global, but here they are kept local because they are formal parameters in the function declaration.
It also uses document.write to write a table in parts, which is never a good idea. I think it's just a poorly written script, find something else.
Im a newbie programmer who got the function below from Stoyan Stefanovs object oriented JavaScript Book. He says that if you call next three times, it will output "a" and "b" and then "c". When I tried it in firebug console, it kept giving me "a", so that`s one question (a) i.e. is there something about firebug that would explain my result?
Next, I tried to run it in jsfiddle.net but it won`t output anything. http://jsfiddle.net/mjmitche/SkSMm/
Im sure Im doing something wrong, but what? Please explain if you can. Note, I did next(); and got A, and then I did next(); again and got 'a' and next(); again and got 'a'. In other words, the counter didnt change or didnt remember.
function setup(x) {
var i = 0;
return function () {
return x[i++];
};
}
var next = setup(['a','b','c']);
next();
Here is the jsfiddle link to show it works:
http://jsfiddle.net/ZnZTk/
JsFiddle is not like the console, it doesn't have a window where it will output return values. The result of the code is a web page, that is shown at the lower right.
You can use the alert method to show the values:
alert(next());
http://jsfiddle.net/SkSMm/4/
As you see, calling next three times will actually output the three values in the array. The setup function returns a delegate to the anonumous function that is created in the function. As that anonymous function uses variables outside itself, but which are local to the surrounding function, a closure is created for the function. The closure will contain the i and x variables. As the closure belongs to the delegate, it will survive from one function call to the next, and retain the values of it's variables.
You could do a similar thing just using global variables:
var x = ['a','b','c'];
var i = 0;
function next() {
return x[i++];
}
alert(next());
alert(next());
alert(next());
As the variables are declared outside the function, they will survive between the function calls.
The drawback of using global variables is that one script easily clashes with another if the variables are not given very unique names. If you use a closure, there is no risk of the variables of one script to conflict with variables of another script.
You did it wrong:
And jsfiddle: http://jsfiddle.net/ZHgW2/
Here's a neat demo that takes advantage of an imported say function and relies on a button:
http://jsfiddle.net/entropo/wxTqR/
This is a great way to test your scripts without relying on the log or alerts.
The say function is from jQuery in Action. Excerpt:
Within this function, we employ the services of a small utility function, say() C,
that we use to emit text messages to a dynamically created element on the page
that we’ll call the “console.” This function is declared within the imported support
script file (jqia2.support.js), and will save us the trouble of using annoying and disruptive alerts to indicate when things happen on our page. We’ll be using this handy function in many of the examples throughout the remainder of the book.