Javascript - Convert HTML input string into mathematical evaluation - javascript

I have been wondering if is possible to use a HTML <input id="in"> (which I could enter lets say 25 / 6 * 3) and output the mathematical evaluation with Javascript, I have written up something which very understandably did not work, would there be any way to make it work?
function go() {
var x = $("#in").val();
alert(parseInt(x))
}
Your answers are much appreciated

Yes you can using the eval() function. Assuming you're input is going to take a value then you can simply call eval(myString) which should return the result.
For example if you execute the following:
alert(eval('3 + 4')); // alerts 7
Be wary though in that anything you do really shouldn't be saved as this could lead to javascript attacks if someone is able to submit some javascript that will run on someone elses browser.

Yes, it is possible to do what you're asking; you just have to use eval(). However, using eval() is not very safe. since this means that any JavasScript code inside #in will be evaluated, which is probably not what you want.
A better way to do this would be to write a parser to parse the mathematical expression and build a syntax tree and then evaluate that.

You can use the expression parser of math.js
alert(math.eval('3 + 4'));

Related

Javascript - generating expressions without operator overloading

I'm using three.js in a js project and I'm trying to calculate if a vector is still in an area like this
var THRESHOLD = 10;
if(!is_in_rect(camera.position - forward * THRESHOLD)))
// do something
where camera.position and foward are THREE.Vector3 objects.
The problem with the approach above, although very readable, is that it's not working since js doesn't support operator overloading. I have to write something like
if(!in_rect(camera.position.clone().add(forward.clone().multiplyScalar(THRESHOLD)))
which looks kinda ugly to me.
Is there any other idiomatic way of doing this in js that I'm missing?
From the page you linked to:
.addScaledVector ( v, s )
Adds the multiple of v and s to this vector
so a bit better is:
camera.position.clone().addScaledVector(forward,THRESHOLD)
Also, there's no real reason to clone forward, as that won't be changed.
If I'm following what #T.J. is saying, and you want something more general, than my answer would be no, if idomatic means using + and -, if we're strictly sticking to JS. You could build your own framework to make things idomatic, such as a general addition operator:
var add = function(x,y):
try {
var sum = x + y;
if ( s != undefined ) { return sum; }
#otherwise
sum = x.clone().add(y);
} catch {
#Otherwise threw something
sum = x.add(y) #maybe another exception? nest try/catch.
}
}
But this is a lot of work, as you would have to type check a lot since JS can add up stuff with impunity. Just trying to return x+y will often be undefined. In my example perhaps testing for add functions before simple additions may be better.
This way you can create the idiom you like, if you think it's worth it, and use your add for everything (instead of + in my example). Probably grow it as you code.
Is there any other idiomatic way of doing this in js that I'm missing?
Not really, no; you'd basically have to write yourself an expression parser, or use one that's already been written.
A couple of notes on that:
Doing that might be a bit easier with ES2015+'s template literals and tagged template functions, since it would do some of the parsing for you. For instance, you might be able to give yourself tag function that would let you write:
if(!is_in_rect(threval`${camera.position} - ${forward} * ${THRESHOLD}`)))
threval would receive an array of the raw strings in that template, followed by the values of camera.position, forward, and THRESHOLD. So you could use that information to build up the sequence. But it would be non-trivial.
You could write yourself a Babel plugin to make your expressions first-class productions, and transpile. The advantage to that is that Babel provides a robust parsing infrastructure and tooling support.

Alternative to eval() javascript [duplicate]

This question already has answers here:
What are the Alternatives to eval in JavaScript?
(11 answers)
Closed 7 years ago.
I work mainly with javascript, Jquery, knockout, etc
The thing that attracted eval() to me is
var a = 5;
var b = 10;
eval("a+b");
//Gives me output 15
Note: I work in cases where the value of a and b changes dynamically
In my work I'm dealing with a lot of dynamic objects from json, knockout, etc. So eval solves most of my problems.
But as I read I found there are so many issues with eval() like slowing down etc.
I searched a lot and haven't found any substitute for eval() when i have to evaluate equation obtaining as string into equation as object.
Can anyone suggest a plugin or function alternative to eval() keeping in mind the example i have given above
Problem:
I'm creating a Table from Json data using knockout mapping. So that what ever the format of json is the table is generated. I also calculate some field using knockout computed.
Right now I use hard-coded
self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })
self.salaryEqn(salEqnTxt);
I want to execute these equations dynamic. I can create it dynamicaly as string but to eval them is the issue I'm facing.
I want solution for
Is there a way to calculate a formula stored in a string in JavaScript without using eval?
Like a formula
"self.Salary = ko.computed(function(){ return self.salaryEqn() && eval(self.salaryEqn()).toFixed(2); })"
Javascript is a very flexible language in this regard. There are very very few cases where eval() is the right answer to any given question, and it certainly isn't necessary here.
If your a and b variables are part of an object, you can access them with string subscripts:
ie myobj.a could also be referenced as myobj['a'].
From that, you can use a variable for the subscript, and thus you can reference any element in myobj dynamically -- ie:
var myobj = {a : 5, b : 10};
var dynamicProperty1 = 'a';
var dynamicProperty2 = 'b';
//gives 15.
alert( myobj[dynamicProperty1] + myobj[dynamicProperty2] );
No eval() required. You can build the dynamicProperty strings however you wish, so there's virtually infinite flexibility.
If your a and b variables are globals, JS globals in the browser are actually children of the window object, so you can still use this technique even with globals.
ie your global variable a could also be accessed via window.a or window['a'], with the latter option allowing you to do the same dynamicProperty trick described above.
Hope that helps.
do you mean that you want to calculate an equation that you can't know until you've received it?
if so see Calculate string value in javascript, not using eval .
in short:
eval CAN be used sometimes, but only if the equation string comes from a trusted source, and there you need something like evaluating dynamic equations.
maybe using window['var' + num] might be more useful for you. i don't quite understand your question sorry.
If you can collect them under an object like root = {a: 1, b: 2}, then
Object.observe(root, function(newValues) {
res = newValues.object.a + newValues.object.b;
});
can keep your res variable up to date whenever the a or b changes
It looks like you are trying to do dynamic equations created by a user.
For example it could be 'a+b+c' or 'dog+cat', and you don't know.
The best way to handle user-input equations like that is to parse the text into tokens and then translate the tokens into values/operands.
That's a lot of work, but there are pre-rolled solutions. For example, math.js
Check more alternatives to eval in this question and another one here which both might be considered a duplicate...
I understand this is a link only answer, but it will for sure be helpful to others searching for alteratives to eval.

How do I convert a string into an executable line of code in Javascript?

I have the following bit of code
console.log("I am");
var x = "console.log('Alive!')";
Now I only want to use x to execute the code-string that is assigned to it - I may not even know the value of x for example but simply want to execute it whatever it maybe - is this possible?
eval() This will convert string to javascript code.
eval("console.log('Alive! Woo!')");
eval and new Function let you parse and execute JavaScript code from strings.
In general, avoid executing code from strings. And never execute code from strings where the strings are untrusted input (for instance, if you take input from user A, never use these to evaluate it in a session with user B).
I see answers here pointing you at eval. eval grants access to your local variables and such to the code, making it really powerful and really dangerous if you use it with untrusted input.
Where possible, avoid eval. You can easily avoid it in your case:
For instance:
console.log("I am");
var x = "console.log('Alive!')";
new Function(x)();
That code creates a function whose body is the text from x, then immediately executes the function.
What you are looking for is eval(). By passing a string to this function you will evaluate the string as JavaScript code and it will return whatever return-value the code in the string returns.
Be aware when using this function though. You do not want to evaluate any code you do not know is safe to execute. For example, running user-generated code could mess up whatever you are making. While using this in JavaScript on a website this will probably only cause issues on the client-side and hence probably won't be much of a security threat, you would want to be VERY careful when evaluating code on for example a server side.
As have been hinted to in other posts here you probably want to make a function instead of an evaluated string if you are in control of the source code that is to be run.
What you are looking for is called a function:
function x() {
console.log('Alive!');
}
If x is already a string containing the code you could use eval(x) to execute it. eval is evil though.
var x = "console.log('Alive!')";
eval(x)

How to detect variable dependencies for a javascript function

Say I have this function:
function test(){
return a + b + 1;
}
How can I dynamically figure out that it will require globals a and b to be able to run? E.g. something like get_dependencies(test) returns ['a', 'b']
There's no built-in way to do that in standard JavaScript, if you're trying to do it with JavaScript itself.
On nearly all (but not all) JavaScript engines, you can get a form of the source of a function from the function object's toString function, e.g.:
var testSource = test.toString();
...and then of course you could parse that. This is non-standard behavior (the result of calling toString on a function is not defined in the specification), but it's widely-supported. You'd still have to do the parsing to find the symbols.
For the parsing, you have a couple of options. You could try to separate the parser portion of JSLint out of the rest of it, or alternately the terribly-named UglifyJS compressor has a full JavaScript parser which is already separate from the compressor part (see parse-js.js; apparently there's a tiny bit of NodeJS-specific stuff you might want to remove).
You can use a Javascript 'lint' tool that will test your code for common mistakes or oddities.
Some can be found online:
http://www.jslint.com/
http://www.javascriptlint.com/online_lint.php (can also be downloaded)
In your case, you might want to isolate individual functions via a regular expression for example, and submit them to such a tool.

Javascript security question / Using eval()

I'm seeing code in the following form - is such use of eval() safe?
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset=eval("document."+frm_name);
var x=eval("document."+frm_name+".edit_key");
var y=eval("document."+frm_name+".cAction")
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
Its used as:
<a href="javaScript:;" onClick="genericTakeAction('frmSearch',
'<?php echo $rec_id;?>','<?php echo $pagenum?>','makeOpen')"
class='link6'>Make Open</a>
Whether it's right or wrong, it's needlessly complicated.
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset = document[frm_name];
var x = rset.edit_key;
var y = rset.cAction;
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
This works because in JavaScript, you can access an object's properties in one of two ways: Either using dotted syntax and a literal identifier, e.g. x = obj.foo;, or using bracket syntax and a string identifier, e.g. x = obj["foo"];. (Note how foo was not in quotes in the first one, but was in quotes for the second; but both do exactly the same thing. Also note that since the property name is a string in the second case, you can use any expression that results in a string, so y = "f"; x = obj[y + "oo"]; also works.)
P.S. It's wrong
eval() is generally frowned upon because, as you are already aware, it is considered unsafe.
In the browser environment, however, it is less of an issue, because in fact, any user could eval() any code they wanted to, using tools like Firebug, etc.
There is still an issue, in that the eval() embedded in the code can be run without the user knowing that he was triggering an eval(), but it's still much less of an issue than in a server-side environment like PHP.
eval() is actually typically used as you've shown to run JSON code being returned from a server-side request. Newer browsers can import JSON more safely using a dedicated JSON parse() function, but older browsers do not have this function and are forced to use eval() for this. Most JSON libraries have eval() in their code somewhere for this reason, but will generally do some sanitisation of the input before running it through eval().
Even if it might look a little bit convoluted, as others have already mentioned, from a pure security perspective, you have to make sure that the 'frm_name' parameter of the genericTakeAction() function can never contain user-supplied data.
In your example, the 'frm_name' parameter contains the hard-coded literal 'frmSearch'. So it is ok as long as this genericTakeAction() function does not get called somewhere else with user-supplied data for the 'frm_name' parameter.
See http://en.wikipedia.org/wiki/Cross-site_scripting#Traditional_versus_DOM-based_vulnerabilities

Categories