Why is using the JavaScript eval function a bad idea? - javascript

The eval function is a powerful and easy way to dynamically generate code, so what are the caveats?

Improper use of eval opens up your
code for injection attacks
Debugging can be more challenging
(no line numbers, etc.)
eval'd code executes slower (no opportunity to compile/cache eval'd code)
Edit: As #Jeff Walden points out in comments, #3 is less true today than it was in 2008. However, while some caching of compiled scripts may happen this will only be limited to scripts that are eval'd repeated with no modification. A more likely scenario is that you are eval'ing scripts that have undergone slight modification each time and as such could not be cached. Let's just say that SOME eval'd code executes more slowly.

eval isn't always evil. There are times where it's perfectly appropriate.
However, eval is currently and historically massively over-used by people who don't know what they're doing. That includes people writing JavaScript tutorials, unfortunately, and in some cases this can indeed have security consequences - or, more often, simple bugs. So the more we can do to throw a question mark over eval, the better. Any time you use eval you need to sanity-check what you're doing, because chances are you could be doing it a better, safer, cleaner way.
To give an all-too-typical example, to set the colour of an element with an id stored in the variable 'potato':
eval('document.' + potato + '.style.color = "red"');
If the authors of the kind of code above had a clue about the basics of how JavaScript objects work, they'd have realised that square brackets can be used instead of literal dot-names, obviating the need for eval:
document[potato].style.color = 'red';
...which is much easier to read as well as less potentially buggy.
(But then, someone who /really/ knew what they were doing would say:
document.getElementById(potato).style.color = 'red';
which is more reliable than the dodgy old trick of accessing DOM elements straight out of the document object.)

I believe it's because it can execute any JavaScript function from a string. Using it makes it easier for people to inject rogue code into the application.

It's generally only an issue if you're passing eval user input.

Two points come to mind:
Security (but as long as you generate the string to be evaluated yourself, this might be a non-issue)
Performance: until the code to be executed is unknown, it cannot be optimized. (about javascript and performance, certainly Steve Yegge's presentation)

Passing user input to eval() is a security risk, but also each invocation of eval() creates a new instance of the JavaScript interpreter. This can be a resource hog.

Mainly, it's a lot harder to maintain and debug. It's like a goto. You can use it, but it makes it harder to find problems and harder on the people who may need to make changes later.

One thing to keep in mind is that you can often use eval() to execute code in an otherwise restricted environment - social networking sites that block specific JavaScript functions can sometimes be fooled by breaking them up in an eval block -
eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');
So if you're looking to run some JavaScript code where it might not otherwise be allowed (Myspace, I'm looking at you...) then eval() can be a useful trick.
However, for all the reasons mentioned above, you shouldn't use it for your own code, where you have complete control - it's just not necessary, and better-off relegated to the 'tricky JavaScript hacks' shelf.

Unless you let eval() a dynamic content (through cgi or input), it is as safe and solid as all other JavaScript in your page.

Along with the rest of the answers, I don't think eval statements can have advanced minimization.

It is a possible security risk, it has a different scope of execution, and is quite inefficient, as it creates an entirely new scripting environment for the execution of the code. See here for some more info: eval.
It is quite useful, though, and used with moderation can add a lot of good functionality.

Unless you are 100% sure that the code being evaluated is from a trusted source (usually your own application) then it's a surefire way of exposing your system to a cross-site scripting attack.

It's not necessarily that bad provided you know what context you're using it in.
If your application is using eval() to create an object from some JSON which has come back from an XMLHttpRequest to your own site, created by your trusted server-side code, it's probably not a problem.
Untrusted client-side JavaScript code can't do that much anyway. Provided the thing you're executing eval() on has come from a reasonable source, you're fine.

It greatly reduces your level of confidence about security.

If you want the user to input some logical functions and evaluate for AND the OR then the JavaScript eval function is perfect. I can accept two strings and eval(uate) string1 === string2, etc.

If you spot the use of eval() in your code, remember the mantra “eval() is evil.”
This
function takes an arbitrary string and executes it as JavaScript code. When the code in
question is known beforehand (not determined at runtime), there’s no reason to use
eval().
If the code is dynamically generated at runtime, there’s often a better way to
achieve the goal without eval().
For example, just using square bracket notation to
access dynamic properties is better and simpler:
// antipattern
var property = "name";
alert(eval("obj." + property));
// preferred
var property = "name";
alert(obj[property]);
Using eval() also has security implications, because you might be executing code (for
example coming from the network) that has been tampered with.
This is a common antipattern when dealing with a JSON response from an Ajax request.
In those cases
it’s better to use the browsers’ built-in methods to parse the JSON response to make
sure it’s safe and valid. For browsers that don’t support JSON.parse() natively, you can
use a library from JSON.org.
It’s also important to remember that passing strings to setInterval(), setTimeout(),
and the Function() constructor is, for the most part, similar to using eval() and therefore
should be avoided.
Behind the scenes, JavaScript still has to evaluate and execute
the string you pass as programming code:
// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);
// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);
Using the new Function() constructor is similar to eval() and should be approached
with care. It could be a powerful construct but is often misused.
If you absolutely must
use eval(), you can consider using new Function() instead.
There is a small potential
benefit because the code evaluated in new Function() will be running in a local function
scope, so any variables defined with var in the code being evaluated will not become
globals automatically.
Another way to prevent automatic globals is to wrap the
eval() call into an immediate function.

EDIT: As Benjie's comment suggests, this no longer seems to be the case in chrome v108, it would seem that chrome can now handle garbage collection of evaled scripts.
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
Garbage collection
The browsers garbage collection has no idea if the code that's eval'ed can be removed from memory so it just keeps it stored until the page is reloaded.
Not too bad if your users are only on your page shortly, but it can be a problem for webapp's.
Here's a script to demo the problem
https://jsfiddle.net/CynderRnAsh/qux1osnw/
document.getElementById("evalLeak").onclick = (e) => {
for(let x = 0; x < 100; x++) {
eval(x.toString());
}
};
Something as simple as the above code causes a small amount of memory to be store until the app dies.
This is worse when the evaled script is a giant function, and called on interval.

Besides the possible security issues if you are executing user-submitted code, most of the time there's a better way that doesn't involve re-parsing the code every time it's executed. Anonymous functions or object properties can replace most uses of eval and are much safer and faster.

This may become more of an issue as the next generation of browsers come out with some flavor of a JavaScript compiler. Code executed via Eval may not perform as well as the rest of your JavaScript against these newer browsers. Someone should do some profiling.

This is one of good articles talking about eval and how it is not an evil:
http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
I’m not saying you should go run out and start using eval()
everywhere. In fact, there are very few good use cases for running
eval() at all. There are definitely concerns with code clarity,
debugability, and certainly performance that should not be overlooked.
But you shouldn’t be afraid to use it when you have a case where
eval() makes sense. Try not using it first, but don’t let anyone scare
you into thinking your code is more fragile or less secure when eval()
is used appropriately.

eval() is very powerful and can be used to execute a JS statement or evaluate an expression. But the question isn't about the uses of eval() but lets just say some how the string you running with eval() is affected by a malicious party. At the end you will be running malicious code. With power comes great responsibility. So use it wisely is you are using it.
This isn't related much to eval() function but this article has pretty good information:
http://blogs.popart.com/2009/07/javascript-injection-attacks/
If you are looking for the basics of eval() look here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

The JavaScript Engine has a number of performance optimizations that it performs during the compilation phase. Some of these boil down to being able to essentially statically analyze the code as it lexes, and pre-determine where all the variable and function declarations are, so that it takes less effort to resolve identifiers during execution.
But if the Engine finds an eval(..) in the code, it essentially has to assume that all its awareness of identifier location may be invalid, because it cannot know at lexing time exactly what code you may pass to eval(..) to modify the lexical scope, or the contents of the object you may pass to with to create a new lexical scope to be consulted.
In other words, in the pessimistic sense, most of those optimizations it would make are pointless if eval(..) is present, so it simply doesn't perform the optimizations at all.
This explains it all.
Reference :
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

It's not always a bad idea. Take for example, code generation. I recently wrote a library called Hyperbars which bridges the gap between virtual-dom and handlebars. It does this by parsing a handlebars template and converting it to hyperscript which is subsequently used by virtual-dom. The hyperscript is generated as a string first and before returning it, eval() it to turn it into executable code. I have found eval() in this particular situation the exact opposite of evil.
Basically from
<div>
{{#each names}}
<span>{{this}}</span>
{{/each}}
</div>
To this
(function (state) {
var Runtime = Hyperbars.Runtime;
var context = state;
return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
return [h('span', {}, [options['#index'], context])]
})])
}.bind({}))
The performance of eval() isn't an issue in a situation like this because you only need to interpret the generated string once and then reuse the executable output many times over.
You can see how the code generation was achieved if you're curious here.

I would go as far as to say that it doesn't really matter if you use eval() in javascript which is run in browsers.*(caveat)
All modern browsers have a developer console where you can execute arbitrary javascript anyway and any semi-smart developer can look at your JS source and put whatever bits of it they need to into the dev console to do what they wish.
*As long as your server endpoints have the correct validation & sanitisation of user supplied values, it should not matter what gets parsed and eval'd in your client side javascript.
If you were to ask if it's suitable to use eval() in PHP however, the answer is NO, unless you whitelist any values which may be passed to your eval statement.

I won't attempt to refute anything said heretofore, but i will offer this use of eval() that (as far as I know) can't be done any other way. There's probably other ways to code this, and probably ways to optimize it, but this is done longhand and without any bells and whistles for clarity sake to illustrate a use of eval that really doesn't have any other alternatives. That is: dynamical (or more accurately) programmically-created object names (as opposed to values).
//Place this in a common/global JS lib:
var NS = function(namespace){
var namespaceParts = String(namespace).split(".");
var namespaceToTest = "";
for(var i = 0; i < namespaceParts.length; i++){
if(i === 0){
namespaceToTest = namespaceParts[i];
}
else{
namespaceToTest = namespaceToTest + "." + namespaceParts[i];
}
if(eval('typeof ' + namespaceToTest) === "undefined"){
eval(namespaceToTest + ' = {}');
}
}
return eval(namespace);
}
//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
//Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
//Code goes here
//this.MyOtherMethod("foo")); // => "foo"
return true;
}
//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);
EDIT: by the way, I wouldn't suggest (for all the security reasons pointed out heretofore) that you base you object names on user input. I can't imagine any good reason you'd want to do that though. Still, thought I'd point it out that it wouldn't be a good idea :)

Related

Is the eval() function safe to use here?

I'm learning DOM Scripting with JavaScript and thought it nice to make a simple calculator app, I found the logic easy enough to do but ran into a problem using parseInt to convert the string type arithmetic expression to number type arithmetic expression.
I ended up having to use the eval() function which worked fine for a basic calculator app but on further research I found out the eval() function is a security risk in most casese, I've used a regex expression to cleanse the result but don't know if this is safe enough.
Here is the code snippet I'm unsure is safe to be executed on the client browser.
const equals = document.getElementById("equals");
equals.addEventListener("click", (e) => {
document.getElementById("result").innerText = eval(document.getElementById("result").innerText).replace(/[^**-+/*\d]/g, '');
});
NOTE: This code is deployed as a static site on Netlify.
You should definitely stop using eval().
Executing JavaScript instructions from a string opens up a huge security risk that makes it easy for would-be third-party attackers to inject potentially malicious code into your application without your knowledge or permission.
Another reason not to use eval(), in my view, is that some sources have already marked it as obsolete or deprecated and it is being blocked by default in some environments due to its security risks and slow performance. In other words, support for eval() is at issue and there is a push to possibly phase it out from future versions of Javascript. That means anything you've built that uses it has the potential to eventually stop working.
The good news is eval() has been on its way out for a quite while now so there are plenty of much better, much more secure ways to accomplish just about everything you'd use eval() for. In fact, the code snippet you shared doesn't need eval() at all.
The innerText property you are updating is directly accessible from within the DOM. While we're on the subject, avoid using the innerHTML property. It too poses security risks similar to eval().
This code here should address your concerns:
const equals = document.getElementById("equals");
equals.addEventListener("click", (e) => {
let result = document.getElementById("result");
result.innerText = result.innerText.replace(/[^**-+/*\d]/g, '');
return true;
});
The only place in a calculator app I can think of where a developer might be tempted to use eval() would be to run it's actual calculations. It's sort of a cheat to just feed an entire mathematical expression to eval() rather than construct a proper parser. I suppose it works (for now) but it's a bad practice.
I built a little calculator app you are welcome to study that performs all the key operations one expects a calculator to do without touching eval(). Feel free to check it out: https://calc-work.webflow.io.
Hope you find this helpful. Cheers!

How can I run a string as if it where javascript code?

How can I run a string
as if it where javascript code?
//The user inputs javascript code and clicks run and it runs the javascript code
function getCode () {
retrun code();
}
funciton runCode() {
run(getCode());
}
The function you want is eval.
function funCode() {
eval(getCode());
};
While eval() certainly works, another option is to take the code, and pass it to the Function constructor. This creates a new function with your code as the function body.
Doing this has some benefits.
it's variable scope will be the global scope, so the code you run won't interfere with any local variables
it has much better performance
you can force the code into strict mode, and can shadow the window and self identifiers, making it difficult to create global variables
funciton runCode() {
// create `window` param---v v--- and `self` param
var f = new Function("window", "self", " 'use strict'; " + getCode())
// force strict mode -----------^
var self = {}
f.call(self, self, self); // pass an object to the `window` and `self` param
// and set the same object as the `this` value
}
This certainly doesn't provide full security, but can provide a little more of a "sandbox" for the code to run in.
You can also examine the self object after the call to see if it tried to create any globals.
It may also be useful to wrap the code or the function execution in a try/catch, and then examine any errors that were thrown.
eval() is the function you're looking for.
But use it wisely or not at all as it's fraught with security risks.
var exec_string = 'alert(\'Hello, World!\')';
eval(exec_string);
Outputs "Hello, World!" in an alert
You can use the built-in eval function:
function runCode() {
eval(getCode());
}
Note that this function is a bit "magical"; the interpreter gives it information from the surrounding lexical context. As a result, it has to be called as eval; you can't set run = eval and then call run. (You could, however, write function run(s) { return eval(s); }.)
As other posters have indicated, eval is the method that exists for this purpose. However, eval will execute any javascript code regardless of whether it is harmful or not (e.g. javascript from a third party source might have an infinite loop or, worse, malicious behaviour). There is the common refrain
eval == evil
and as such eval is generally regarded as an anti-pattern. However, taking such a simplistic approach is wrong. Instead, it is perfectly acceptable to use eval in cases where the string you wish to evaluate can be trusted. However it turns out there are relatively few cases where this is true. Obviously anything from a third party site is dangerous (even if you trust the owners, they may have been hacked). Even from your own server you may be susceptible to "man in the middle" attacks although this is fairly unlikely for most sites.
The most common reason to need to evaluate javascript strings is rendering third party web pages. In this case it is generally preferable to render the page on the server (e.g. http://phantomjs.org/) and then transmit the result to the browser. That way the browser is protected from running unsafe code.
Another, increasingly common, use case is interactive tutorial websites where the user gets to see the result of the code they have typed in. In this case you are less worried about malicious scripts as the only ones the user will suffer from are those that he/she has typed themselves. But in this case you are still worried about mistakes that will break the functionality of your site (e.g. infinite loops) and so it is still recommended to carry out the evaluation on your server (with appropriate safeguards) so that the inputed javascript cannot break anything.
A possible alternative to eval is Google's caja (https://code.google.com/p/google-caja/) which intends to solve all these problems, however I've never used it myself and can't comment on its usefulness.

What are the benefits to using anonymous functions instead of named functions for callbacks and parameters in JavaScript event code?

I'm new-ish to JavaScript. I understand many of the concepts of the language, I've been reading up on the prototype inheritance model, and I'm whetting my whistle with more and more interactive front-end stuff. It's an interesting language, but I'm always a bit turned off by the callback spaghetti that is typical of many non-trivial interaction models.
Something that has always seemed strange to me is that in spite of the readability nightmare that is a nest of JavaScript nested callbacks, the one thing that I very rarely see in many examples and tutorials is the use of predefined named functions as callback arguments. I'm a Java programmer by day, and discarding the stereotypical jabs about Enterprise-y names for units of code one of the things I've come to enjoy about working in a language with a strong selection of featureful IDE's is that using meaningful, if long, names can make the intent and meaning of code much clearer without making it more difficult to actually be productive. So why not use the same approach when writing JavaScript code?
Giving it thought, I can come up with arguments that are both for and against this idea, but my naivety and newness to the language impairs me from reaching any conclusions as to why this would be good at a technical level.
Pros:
Flexibility. An asynchronous function with a callback parameter could be reached by one of many different code paths and it could be harried to have to write a named function to account for every single possible edge case.
Speed. It plays heavily in to the hacker mentality. Bolt things on to it until it works.
Everyone else is doing it
Smaller file sizes, even if trivially so, but every bit counts on the web.
Simpler AST? I would assume that anonymous functions are generated at runtime and so the JIT won't muck about with mapping the name to instructions, but I'm just guessing at this point.
Quicker dispatching? Not sure about this one either. Guessing again.
Cons:
It's hideous and unreadable
It adds to the confusion when you're nested nuts deep in a swamp of callbacks (which, to be fair, probably means you're writing poorly constructed code to begin with, but it's quite common).
For someone without a functional background it can be a bizarre concept to grok
With so many modern browsers showing the ability to execute JavaScript code much faster than before, I'm failing to see how any trivial sort of performance gain one might get out using anonymous callbacks would be a necessity. It seems that, if you are in a situation where using a named function is feasible (predictable behavior and path of execution) then there would be no reason not to.
So are there any technical reasons or gotchas that I'm not aware of that makes this practice so commonplace for a reason?
I use anonymous functions for three reasons:
If no name is needed because the function is only ever called in one place, then why add a name to whatever namespace you're in.
Anonymous functions are declared inline and inline functions have advantages in that they can access variables in the parent scopes. Yes, you can put a name on an anonymous function, but that's usually pointless if it's declared inline. So inline has a significant advantage and if you're doing inline, there's little reason to put a name on it.
The code seems more self-contained and readable when handlers are defined right inside the code that's calling them. You can read the code in almost sequential fashion rather than having to go find the function with that name.
I do try to avoid deep nesting of anonymous functions because that can be hairy to understand and read. Usually when that happens, there's a better way to structure the code (sometimes with a loop, sometimes with a data table, etc...) and named functions isn't usually the solution there either.
I guess I'd add that if a callback starts to get more than about 15-20 lines long and it doesn't need direct access to variables in the parent scope, I would be tempted to give it a name and break it out into it's own named function declared elsewhere. There is definitely a readability point here where a non-trivial function that gets long is just more maintainable if it's put in its own named unit. But, most callbacks I end up with are not that long and I find it more readable to keep them inline.
I prefer named functions myself, but for me it comes down to one question:
Will I use this function anywhere else?
If the answer is yes, I name/define it. If not, pass it as an anonymous function.
If you only use it once, it doesn't make sense to crowd the global namespace with it. In today's complex front-ends, the number of named functions that could have been anonymous grows quickly (easily over 1000 on really intricate designs), resulting in (relatively) large performance gains by preferring anonymous functions.
However, code maintainability is also extremely important. Each situation is different. If you're not writing a lot of these functions to begin with, there's no harm in doing it either way. It's really up to your preference.
Another note about names. Getting in the habit of defining long names will really hurt your file size. Take the following example.
Assume both of these functions do the same thing:
function addTimes(time1, time2)
{
// return time1 + time2;
}
function addTwoTimesIn24HourFormat(time1, time2)
{
// return time1 + time2;
}
The second tells you exactly what it does in the name. The first is more ambiguous. However, there are 17 characters of difference in the name. Say the function is called 8 times throughout the code, that's 153 extra bytes your code didn't need to have. Not colossal, but if it's a habit, extrapolating that to 10s or even 100s of functions will easily mean a few KB of difference in the download.
Again however, maintainability needs to be weighed against the benefits of performance. This is the pain of dealing with a scripted language.
A bit late to the party, but some not yet mentioned aspects to functions, anonymous or otherwise...
Anon funcs are not easily referred to in humanoid conversations about code, amongst a team. E.g., "Joe, could you explain what the algorithm does, within that function. ... Which one? The 17th anonymous function within the fooApp function. ... No, not that one! The 17th one!"
Anon funcs are anonymous to the debugger as well. (duh!) Therefore, the debugger stack trace will generally just show a question mark or similar, making it less useful when you have set multiple breakpoints. You hit the breakpoint, but find yourself scrolling the debug window up/down to figure out where the hell you are in your program, because hey, question mark function just doesn't do it!
Concerns about polluting the global namespace are valid, but easily remedied by naming your functions as nodes within your own root object, like "myFooApp.happyFunc = function ( ... ) { ... }; ".
Functions that are available in the global namespace, or as nodes in your root object like above, can be invoked from the debugger directly, during development and debug. E.g., at the console command line, do "myFooApp.happyFunc(42)". This is an extremely powerful ability that does not exist (natively) in compiled programming languages. Try that with an anon func.
Anon funcs can be made more readable by assigning them to a var, and then passing the var as the callback (instead of inlining). E.g.:
var funky = function ( ... ) { ... };
jQuery('#otis').click(funky);
Using the above approach, you could potentially group several anon funcs at the top of the parental func, then below that, the meat of sequential statements becomes much tighter grouped, and easier to read.
Anonymous functions are useful because they help you control which functions are exposed.
More Detail: If there is no name, you can't reassign it or tamper with it anywhere but the exact place it was created. A good rule of thumb is, if you don't need to re-use this function anywhere, it's a good idea to consider if an anonymous function would be better to prevent getting tampered with anywhere.
Example:
If you're working on a big project with a lot of people, what if you have a function inside of a bigger function and you name it something? That means anyone working with you and also editing code in the bigger function can do stuff to that smaller function at any time. What if you named it "add" for instance, and someone reassigned "add" to a number instead inside the same scope? Then the whole thing breaks!
PS -I know this is a very old post, but there is a much simpler answer to this question and I wish someone had put it this way when I was looking for the answer myself as a beginner- I hope you're ok with reviving an old thread!
Its more readable using named functions and they are also capable of self-referencing as in the example below.
(function recursion(iteration){
if (iteration > 0) {
console.log(iteration);
recursion(--iteration);
} else {
console.log('done');
}
})(20);
console.log('recursion defined? ' + (typeof recursion === 'function'));
http://jsfiddle.net/Yq2WD/
This is nice when you want to have an immediately invoked function that references itself but does not add to the global namespace. It's still readable but not polluting. Have your cake and eat it to.
Hi, my name is Jason OR hi, my name is ???? you pick.
Well, just to be clear for the sake of my arguments, the following are all anonymous functions/function expressions in my book:
var x = function(){ alert('hi'); },
indexOfHandyMethods = {
hi: function(){ alert('hi'); },
high: function(){
buyPotatoChips();
playBobMarley();
}
};
someObject.someEventListenerHandlerAssigner( function(e){
if(e.doIt === true){ doStuff(e.someId); }
} );
(function namedButAnon(){ alert('name visible internally only'); })()
Pros:
It can reduce a bit of cruft, particularly in recursive functions (where you could (should actually since arguments.callee is deprecated) still use a named reference per the last example internally), and makes it clear the function only ever fires in this one place.
Code legibility win: in the example of the object literal with anon funcs assigned as methods, it would be silly to add more places to hunt and peck for logic in your code when the whole point of that object literal is to plop some related functionality in the same conveniently referenced spot. When declaring public methods in a constructor, however, I do tend to define labeled functions inline and then assign as references of this.sameFuncName. It lets me use the same methods internally without the 'this.' cruft and makes order of definition a non-concern when they call each other.
Useful for avoiding needless global namespace pollution - internal namespaces, however, shouldn't ever be that broadly filled or handled by multiple teams simultaneously so that argument seems a bit silly to me.
I agree with the inline callbacks when setting short event handlers. It's silly to have to hunt for a 1-5 line function, especially since with JS and function hoisting, the definitions could end up anywhere, not even within the same file. This could happen by accident without breaking anything and no, you don't always have control of that stuff. Events always result in a callback function being fired. There's no reason to add more links to the chain of names you need to scan through just to reverse engineer simple event-handlers in a large codebase and the stack trace concern can be addressed by abstracting event triggers themselves into methods that log useful info when debug mode is on and fire the triggers. I'm actually starting to build entire interfaces this way.
Useful when you WANT the order of function definition to matter. Sometimes you want to be certain a default function is what you think it is until a certain point in the code where it's okay to redefine it. Or you want breakage to be more obvious when dependencies get shuffled.
Cons:
Anon functions can't take advantage of function hoisting. This is a major difference. I tend to take heavy advantage of hoisting to define my own explicitly named funcs and object constructors towards the bottom and get to the object definition and main-loop type stuff right up at the top. I find it makes the code easier to read when you name your vars well and get a broad view of what's going on before ctrl-Fing for details only when they matter to you. Hoisting can also be a huge benefit in heavily event-driven interfaces where imposing a strict order of what's available when can bite you in the butt. Hoisting has its own caveats (like circular reference potential) but it is a very useful tool for organizing and making code legible when used right.
Legibility/Debug. Absolutely they get used way too heavily at times and it can make debug and code legibility a hassle. Codebases that rely heavily on JQ, for instance, can be a serious PITA to read and debug if you don't encapsulate the near-inevitable anon-heavy and massively overloaded args of the $ soup in a sensible way. JQuery's hover method for instance, is a classic example of over-use of anon funcs when you drop two anon funcs into it, since it's easy for a first-timer to assume it's a standard event listener assignment method rather than one method overloaded to assign handlers for one or two events. $(this).hover(onMouseOver, onMouseOut) is a lot more clear than two anon funcs.

Why is it bad to make elements global variables in Javascript?

I've heard that it's not a good idea to make elements global in JavaScript. I don't understand why. Is it something IE can't handle?
For example:
div = getElementById('topbar');
I don't think that's an implementation issue, but more a good vs bad practice issue. Usually global * is bad practice and should be avoided (global variables and so on) since you never really know how the scope of the project will evolve and how your file will be included.
I'm not a big JS freak so I won't be able to give you the specifics on exactly why JS events are bad but Christian Heilmann talks about JS best practices here, you could take a look. Also try googling "JS best practices"
Edit: Wikipedia about global variables, that could also apply to your problem :
[global variables] are usually
considered bad practice precisely
because of their nonlocality: a global
variable can potentially be modified
from anywhere, (unless they reside in
protected memory) and any part of the
program may depend on it. A global
variable therefore has an unlimited
potential for creating mutual
dependencies, and adding mutual
dependencies increases complexity. See
Action at a distance. However, in a
few cases, global variables can be
suitable for use. For example, they
can be used to avoid having to pass
frequently-used variables continuously
throughout several functions.
via http://en.wikipedia.org/wiki/Global_variable
Is it something IE can't handle?
No it is not an IE thing. You can never assume that your code will be the only script used in the document. So it is important that you make sure your code does not have global function or variable names that other scripts can override.
Refer to Play Well With Others for examples.
I assume by "events" you mean the event-handling JavaScript (functions).
In general, it's bad to use more than one global variable in JS. (It's impossible not to use at least one if you're storing any data for future use.) That's because it runs into the same problem as all namespacing tries to solve - what if you wrote a method doSomething() and someone else wrote a method called doSomething()?
The best way to get around this is to make a global variable that is an object to hold all of your data and functions. For example:
var MyStuff = {};
MyStuff.counter = 0;
MyStuff.eventHandler = function() { ... };
MyStuff.doSomething = function() { ... };
// Later, when you want to call doSomething()...
MyStuff.doSomething();
This way, you're minimally polluting the global namespace; you only need worry that someone else uses your global variable.
Of course, none of this is a problem if your code will never play with anyone else's... but this sort of thinking will bite you in the ass later if you ever do end up using someone else's code. As long as everyone plays nice in terms of JS global names, all code can get along.
There shouldn't be any problem using global variables in your code as long as you are wrapping them inside a uniqe namespase/object (to avoid collision with scripts that are not yours)
the main adventage of using global variable in javascript derives from the fact that javascript is not a strong type language. there for, if you pass somes complex objects as arguments to a function, you will probebly lose all the intellisence for those objects (inside the function scope.)
while using global objects insteads, will preserve that intellisence.
I personally find that very usfull and it certainly have place in my code.
(of course, one should alwayse make the right balance between locales and globals variables)

Javascript clarity of purpose

Javascript usage has gotten remarkably more sophisticated and powerful in the past five years. One aspect of this sort of functional programming I struggle with, esp with Javascript’s peculiarities, is how to make clear either through comments or code just what is happening. Often this sort of code takes a while to decipher, even if you understand the prototypal, first-class functional Javascript way. Any thoughts or techniques for making perfectly clear what your code does and how in Javascript?
I've asked this question elsewhere, but haven't gotten much response.
The use of a common library is one thing, but I think a lot of "getting" JavaScript is simply spending time writing it. Things that may seem esoteric will slowly become mundane. This is true of just about any language or framework.
Many of the idioms used in JavaScript, such as anonymous functions, literal syntax, etc. only seem strange when you are first exposed to them. I think the same rules for writing understandable C#/Java/C++/VB/etc. code apply to JavaScript - use variable names that have semantic meaning, write comments that help someone understand intent and acknowledge assumptions, be explicit, etc.
Now, if you are really asking "how can I make JavaScript understandable to someone that is not familiar with it?" you have another issue - JavaScript is JavaScript and developers just have to do the hard work of learning it before they can be proficient in it and become "at one" with it.
For example, this function may seem very strange to those that are not familiar with JavaScript, but for me (and I am certain many others) it isn't that hard to figure out:
// comments are not included *on purpose* for illustrating
// my point about the need for language knowledge
function copy(obj) {
return new (function(o) {
for(var property in o) {
if(o[property].constructor == Array) {
this[property] = [];
for(var i = 0; i < o[property].length; i++) {
this[property][i] = new arguments.callee(o[property][i]);
}
} else if(o[property].constructor == Object) {
this[property] = new arguments.callee(o[property]);
} else {
this[property] = o[property];
}
}
})(obj);
}
The fact that this function has a name helps the casual reader know what it does, but to really understand what it is doing, one has to have an understanding of why this function might be necessary, how JavaScript object properties can be referenced, what data types JavaScript supports, how constructor functions work, how anonymous functions work, etc. Only a decently deep knowledge of those things are going to help (or a library that has literally everything but the kitchen sink).
UPDATE: To those that say comments in the above sample would lend help to the developer attempting to understand it - obviously. Comments are useful and I think that is a given. The above sample code was meant to illustrate multiple JavaScript-specific idiosyncrasies that are only going to be understood by someone with deep enough knowledge about the language.
As I said in the comments on someone else's answer, my code, which I can completely understand based on my JavaScript knowledge, shouldn't need to be so commented that it becomes a substitute for language knowledge. I shouldn't have to explain, for example, where an anonymous function is or that I am using one in the above code as an anonymous constructor function and that it will alter the perceived standard behavior (to C# and Java devs) of the this keyword, all things that are going to confuse lesser JavaScript developers.
One good way to do this is to use the principles of Unobtrusive JavaScript to separate concerns. The use of jQuery as suggested by Sebastian used this principle.
Unobtrusive JavaScript
My opinion is twofold:
Learn the language. JavaScript closures and {key: {function}} are not that hard to understand. In fact, it's a pretty common dialect.
Learn the framework. jQuery, prototype, etc. are all great frameworks that tries to follow a principle of regularity and homogeneity along all the API. If you grasp this way of doing things in your own JavaScript code, things become clear.
For example, I recently needed a method for applying custom behavior to some inputs. Instead of going functional style, I extended all the <input> elements with my method (I'm using prototype), which goes in line with the rest of the prototype stuff. If one keeps these kinds of principles in mind when developing, most of the code becomes pretty straightforward.
My biggest complaint for JavaScript is to know how to organize my .js files, but that's another story.
I think it is one of the aims of those frameworks like prototype or jQuery to hide most of the JavaScript stuff. Since it is not easy to understand it, they are designed to be as easy as can be.
Therefore if you use such frameworks JavaScript gets cleaner. What I do is to write many many comments, use a lot of whitespace and lines and so on. But those {{function(){... stories remain.
Don't forget that when you write (or come across) a particularly esoteric bit of code, you should probably consider explaining what it's doing (and why it's doing it) with a quick comment, which will help anyone else who has to read the code, but who might not be literate enough in the language to understand what's actually happening.
#Jason Bunting
I've got to say I disagree that "only a decently deep knowledge" of the ins and outs of javascript will help one's understanding of your copy() example. Comments along the lines of "deep copy" or "recursive call to copy object properties" and so forth can quickly elucidate for the programmer who isn't green behind the ears but doesn't know all the particulars of Javascript's peculiarities.
I know there are a number of important concepts to pick up before you can really know Javascript, but that doesn't mean code can't be clearer at a glance.
Format your code. If you have no idea how to use it - rely on IDE ( NetBeans or WebStorm has it inbuilt ) or JS Beautyfier ( if you are still coding in Notepad, for some reason. )
Use general principles for clean code. Use brackets, stick to one code convention, use comprehensible naming scheme, comment sparingly, avoid global variables, deep nesting, long functions and esoteric code.
Make sure your IDE can recognize your code. Often this means you have to scrap module pattern aka power constructor var module = ( function () { ... } )(); in favor of classic constructor Module = function () { ... }; Module.prototype.method1 = function () { ... };
Declare vars in the beginning of function, to avoid well known problems with variable hoisting.
Replace this in constructors with better name. Which somehow shows actual object purpose. function Car() { _car = this; _car.accelerate = function () { ... }; }
Write cross-browser code for modern browsers, and, if you need support for old crap like IE8 and below - use jQuery or other framework. Avoid doing browser detection anywhere after your initializer function, if possible.
Use JS Doc, when you can - i.e. if your IDE or repo-browser supports it.
Write for debug, when your code is really complex. i.e.: do not function() { return { huge chunks of code, do not abuse chaining, do not inline things that might break.
Do not use eval, neither standalone, nor implicit eval in setTimeout or addEventListener.

Categories

Resources