What are the performance implications of using `eval` in Javascript? - javascript

I am toying around with making a custom Javascript class system and am currently interested in making my object instances be well identified in the console / devtools, as described in this previous question of mine. So far, I am getting the impression that the only way to achieve what I want is to to use eval to create named functions, as described in this other question.
Are there any tradeoffs I should expect if I use eval to create my classes? I am not worried about eval itself being slow1 or about security2 but I heard that using eval could possible disable JIT compilation for the rest of the code. Is this true? If it is, what code would be affected? Just the function with eval? The function and all its parent functions? The whole module? What steps could I take to make sure the eval affects my code as little as possible?
1 I would only need to use eval to do some metaprogramming at the start of the script. It wouldnt run inside a performance critical loop.
2 I would never call eval with user input and in my case I could even use a regex to check if the input string is a valid identifier / function name.

Related

Is it possible to write every function as "pure function" in Google Apps Script?

I am interested in functional programming, so I decided to try this approach on the scripting environment of my Google Sheets file, and you know that the scripting language is Google Apps Script, which is basically javascript. And it even supports some (if not all) ES6 syntax.
The problem is that I cannot directly run any code, for example:
let a = 4;
Logger.log(a);
I mean, I cannot run it globally, I need to define a function with any name, and then place the code inside that function, and I can run the function, so the function runs the code inside.
So, maybe you ask, "why this behavior makes a problem writing pure functional code?" well, because, as I know, two of the most important factors about pure functions are:
1) We must not use global variables/functions inside a function, instead we must pass as parameters (and then as arguments of course).
2) defining function inside a function is often not very good idea in terms of readability and organization of the code.
So, I want to define more functions (to do some stuff), not just one "main" function, and I could not find any way, any single way to write code (as a whole) without violating at least one of the two statements above.
So, I mean, I can not write anything without making at least one non-pure function.
As a user explained in the comments:
Your 1st assumption is partially incorrect. A function must not depend on global, mutable variables, but it may depend on global constants and global pure functions. However, often you rather want to pass a function dependency as an argument to obtain a more general higher order function. Your 2nd assumption is merely opinion based.
So you could, for example, define a main function to run your code as a whole while defining functions inside the main function to achieve functional programming with Apps Script.

Should I use eval to patch/extend a widget?

This question may be too opinion based but since avoiding eval is almost unanimously agreed upon, I'd imagine there should be objective answers.
I'd like to "patch" an existing open-source widget to avoid creating my own custom build of it. But the parts I want to patch are internal functions which are completely hidden. IE:
function dostuff(){
function iCantBeEdittedSinceImNotAPrototypeMethod_unlessDoStuffIsCompletelyOverwrittenButItsVeryLong(){
//code that needs patched
};
};
The only way I can see of doing this is to turn the function dostuff into text, search and replace iCantBeEditted and then eval it.
How bad is this use of eval?
And the specific context that I'd like to use this with is fullcalendar's compareSegs function that decides sorts the order of events.
Concerns:
safety of eval
modifying a minified file. I can find the desired function with a somewhat fail safe pattern but even if I make it variable name agnostic, this could cause problems when fullcalendar is updated.
performance. This file is 72kb after being minified.
So, should I do this? Is there an easier alternative?

Why does eval() exist?

Many programmers say it is a bad practice to use the eval() function:
When is JavaScript's eval() not evil?
I'd like to take a moment to address the premise of your question - that eval() is "evil"...
Is this eval() dangerous?
Buggy evaled code can violate security properties just as easily as buggy source code...
Why not eval() JSON?
There are a number of ways that your security may be compromised...
Is there ever a good reason to use eval()?
Yes - when there is no other way to accomplish the given task with a reasonable level of clarity... This eliminates 99% of cases where eval is used...
Why is eval unsafe in javascript?
The danger of eval only rears its ugly head when you are serving a script written by alice to user bob for bob's browser to eval...
So why does it exist in the first place?
Because sometimes there is a need. All the same reasons for/against using eval in JavaScript can likely be shared with the use of reflection in Java, for example.
However, I agree with everything you quoted in your question. Many reasons for using it are ill-advised, and best done differently - but sometimes, there is still a need, or it is simply the "best choice" over other available alternatives. (I'd focus on the answers to Is there ever a good reason to use eval()? for additional reasons.)
+1 to your question for good research.
eval() exists because sometimes you want to give complete programmatic control of your application to code passed in at run time.
Languages without an eval() feature can definitely provide (a subset? all?) of this functionality by asking each programmer to essentially write their own eval() -- lex the input, parse the input, create new objects as necessary, run methods or functions on them via simple string comparisons or similar. In essence, duplicate the entire interpreter that already exists and is debugged and fast.
Eval is actually a powerful feature and there are some things that are impossible to do without it. For example:
Evaluate code received from a remote server. (Say you want to make a site that can be remotely controlled by sending JavaScript code to it?)
Evaluate user-written code. Without eval, you can't program, for example, an online editor/REPL.
Creating functions of arbitrary length dynamically (function.length is readonly, so the only way is using eval).
Loading a script and returning it's value. If your script is, for example, a self-calling function, and you want to evaluate it and get it's result (eg: my_result = get_script_result("foo.js")), the only way of programming the function get_script_result is by using eval inside it.
Re-creating a function in a different closure.
And anything else you'd want to do that involves creating code on the fly.
The reason it is considered "evil" is because it's classicaly used by novices to do things that the language can handle natively. For example, the code below:
age_of_erick = 34;
age_of_john = 21;
person = "erick";
eval("console.log('age_of_"+person+"')");
And the code below:
age = {erick:34, john:21};
person = "erick";
console.log(age["erick"]);
Both do the same thing, except one parses a string, generates code from it, compiles into machine code and then runs, while the other reads a value from a hash, which is a lot faster.
There's a research publication exacty on this topic:
The Eval That Men Do -- A Large-scale Study of the Use of Eval in JavaScript Applications
Mirror on Wayback Machine
It is to me the most comprehensive answer to this question to date.
Quote from the abstract:
We have recorded the behavior of 337 MB of strings given as
arguments to 550,358 calls to the eval function exercised in over
10,000 web sites.
Amongst other, they identified 9 categories of recurring eval:
JSON - A JSON string or variant.
JSONP - A padded JSON string.
Library -One or more function definitions.
Read - Read access to an
object’s property.
Assign - Assignment to a local variable or
object property.
Typeof - Type test expression.
Try - Trivial
try/catch block.
Call - Simple function/method call.
Empty -
Empty or blank string.
A snippet from the conclusion (which is too long to be quoted entierly):
[...] While many uses eval were legitimate, many were unnecessary and
could be replaced with equivalent and safer code. We started this work
with the hope that it would show that eval can be replaced by other
features. Unfortunately our data does not support this conclusion.[...]
A paper well worth reading.
The eval() feature is like scissors. You're an adult, it's your responsibility to not run with them.
I've seen the design philosophy of dynamic languages (like JavaScript) summarised as preferring to enable smart people to do clever things above trying to prevent stupid people from doing silly things. (Unfortunately I can't recall the original source or phrasing.)
If you're worried about introducing bugs with eval, you can use strict mode. It seems to prevent some of the problems with how the feature is designed. (That is, as a "magic" function allowed to clobber your namespace.)
Eval exists to simplify tasks in JavaScript. You can use it evaluate multiple statements. Instead of having to find another way you can use eval to do such things. Even though it is discouraged it has considerable power and use.

A question about eval() in javascript... why is it evil and how can I accomplish the same thing without using it?

I have an application script that is working correctly, but I have a few eval() statements in order to make things work. I don't really understand why "eval is evil", as I keep reading, but what I really don't understand is how to avoid using it when it's the only thing that does what I need it to do.
In my script, I have a bunch of products. Each product has its own array of properties. There is also an array of all of the array names. As I run through different functions, these arrays are used to build the page content. The only method I found that works was to do this:
var schedule = {};
$.each(productNameArray, function (i, name) {
schedule = eval(name);
// DO STUFF
});
Simply using name passes a string and does not read the actual array it is meant to reference. Eval makes it work as an object.
So how do accomplish this without using eval()?
What you are doing is parsing a JSON (like) string. That is one of the few cases, where eval actually isn't evil.
If you can trust the server 100% from which the data arrives at the client, it's not a real problem at all (talking about security issues with eval).
If that is not the case, you always should avoid using eval() since any code that is evaluated has access to your global window object, cookies, DOM etc. and be used to spy & send data around.
The second big topic about why eval is evil is performance. eval() is slow when it comes to actually interpret ECMAscript code. Thats for example, using setTimeout like
setTimeout("myfunction();", 2000); // don't do that
This should always be written like
setTimeout(myfunction, 2000);
Letting Javascript parse Javascript, has a big performance impact.
Eval Evil.
Eval is evil as eval'd code cannot be optimised by javascript interpreters and minifiers which could cause quite a lot of issues because of that (perhaps the interpreter or minifier understands it wrong, or due to the conversion stuffs up the eval'd scope). The other side of the coin is that typically 99% of eval'd code could be rewritten to not use eval - it may require a ton of thinking and problem solving but typically that is the case.
How to avoid using it.
what I really don't understand is how to avoid using it when it's the only thing that does what I need it to do.
Simply using name passes a string and does not read the actual array it is meant to reference. Eval makes it work as an object.
You could use an object to store the variables that you are wanting to reference, and then use obj[name]. However without full code this is just a speculation... which should appear to be suitable.

What is the intended purpose of eval in JavaScript? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
When is JavaScript’s eval() not evil?
I know, generally using eval() is bad practice.
But for what purpose it is existed there?
What is the correct purpose of eval()?
At what situation it is better to use eval()?
eval() provides access to the JavaScript compiler and this ultimately allows for code to be executed at a later time. The arguments passed to the function are passed to the JavaScript compiler after which the code is executed.
Developers argue about the security of eval(). It is less secure, but if you're absolutely sure your input is sanitized before passing it along, then it shouldn't be a problem.
Also, the results of eval() are generally slower because the code has not yet been compiled nor cached. There's obviously going to be a performance hit for using the function.
It's also difficult to debug code that results from the use of eval() because there is little-to-no contextual information (think line numbers) about the code that is ultimately executed.
In terms of web development, one of the current most popular uses of eval() is to deserialize a JSON string usually in the context of Ajax applications; however, this isn't to say that there aren't many other uses.
eval
Evaluates a string of JavaScript code
without reference to a particular
object.
If you construct an arithmetic expression as a string, you can use eval to evaluate it at a later time. For example, suppose you have a variable x. You can postpone evaluation of an expression involving x by assigning the string value of the expression, say "3 * x + 2", to a variable, and then calling eval at a later point in your script.
Be careful when using eval
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension.
You might want to check this article, below is a direct quote from the page which sums up the power of eval.
The JavaScript EVAL command can be
very powerful when using dynamic
content in Web-based applications.
EVAL can reduce code and eases
interaction with data that is unknown
at load time, but there are drawbacks
to take into account.
The real power of this command is its
ability to work with data that is not
known at load time—for example,
user-entered data. As I have
mentioned, EVAL takes any string that
you provide and executes it returning
a result, if one is applicable. You
can use this to execute JavaScript
where what you are being asked to
execute is not known at load time. For
example if we have a calculation
script that takes an equation provided
by the user and returns a result, you
can use EVAL to perform the
calculation.
I don't think it's so much bad to use it as dangerous. People say don't use eval because it opens loopholes for abuse. It's OK to use it if your input is safe. It is used in Doug Crockford's JSON parser, for example, after the input has been checked using a regular expression to make sure there is no "dangerous" content.
The other reason people tell you not to use it is that if you use eval too much, people will start calling you Eval Knievel.
I was experimenting recently with the eval() command while trying to come up with a new convention for a new project.
What I wanted was this: I liked the idea of having private, public, and privileged methods, ala. Doug Crockford's article, but I wanted to be able to expose public methods/variables at the TOP of my classes instead of at the bottom as is usual.
Consider this:
var Singleton = function() {
// Private
function _one() {
// code...
}
function _two() {
// code...
}
// Public
return {
one: _one,
two: _two
};
}();
With three eval()'s (two nested inside of the main one) I was able to have this syntax:
var Singleton = function() {
// Public
var $interface = {
one: $forward,
two: $forward
};
// Private
function _one() {
// code...
}
function _two() {
// code...
}
// This does the magic
return eval($init);
}('Singleton');
And against all odds and common-sense it did work. (Note that I also wanted a way to debug my namespaces which is why you can see a string passed to the singleton. $init took care of this too.)
Anyway, I guess the point of typing all this is to say that eval() isn't necessarily the diseased runt of the JavaScript litter that should be avoided at all costs, and can be used in more ways than just on (trusted!) code sent from a server and JSON de-serializing.
(Although in my case it ended up as a mental-workout, as I had since convinced myself not to bother with private-methods/variables after all and just use a strict namespacing convention.)

Categories