So I really couldn't find much on this. The idea is that I have a user input (text) and I want to check if its valid code in JS and then run it if it is.
I know that I can do if (typeof userInput === "function") { if the userInput was actually a function, but the user input is just a string input at this point, so I'm quite stuck, and it also contains any arguments or other code.
As an example, the input may be "alert('test')" and that would be valid, and I would like to run that, however something like "madeUpFunction(lol)" would be invalid.
I'm happy if I can just get functions working and not any JS code.
You can extract the string up until the first ( in order to get the function name, and then test that it exists using typeof eval(funcName). Then use the Function constructor to make sure that the syntax is valid for the rest of the arguments without actually executing the code.
You can then return the function which executes what the user entered, but note that there may be security issues if you decide to execute the function.
function parseFunctionCall(str) {
var funcName = str.slice(0, str.indexOf('('));
if (typeof eval(funcName) === 'function') {
return new Function(str);
} else {
throw new Error('Invalid function name');
}
}
console.log(parseFunctionCall("console.log('hi')"));
You can use eval("typeof "+ input) to achieve what you want. The argument of the eval() function is a string. If the string represents an expression, eval() evaluates the expression.
var myFunc = function(){};
var input = prompt('Enter input string');
if(eval("typeof "+input) === "function"){
document.getElementById('d1').innerHTML = "Yes it's a funtion";
}
else{
document.getElementById('d1').innerHTML = "Not a funtion";
}
<div id="d1">
</div>
Assuming this is in a browser and that that function you want to check is in the global scope:
if (typeof window[userInput] === "function" ) {
...
}
I am doing this for a calculator project, I want to check if the operation is valid or not, somehow I cannot check for the Boolean value of eval if it is false? on the console:
Boolean(eval('2+2(9.1-)9'));
Boolean(2+2(9.1-)9); // Both operations return unexpected token
unlike Boolean(2+2) <-- returns true. Help?
You actually don't need to evaluate the code in order to see if it's valid - just try creating a Function:
function checkIt() {
var fn
try {
var fn = new Function(document.getElementById("code").value)
alert("Great, that's a valid piece of code!")
} catch (e) {
alert("That's not a valid piece of code.")
}
}
<input id="code">
<button onclick="checkIt()">Check it</button>
For example, try "123", "valid", and "''not[valid!!!".
Though if you are going to be evaluating it right away, if it's valid, you should probably just check if the error is a syntax error, or otherwise.
function doIt() {
var fn
try {
var result = eval(document.getElementById("code").value)
alert("The result is: " + result)
} catch (e) {
if (e instanceof SyntaxError) {
alert("That's not a valid piece of code.")
} else {
alert(e.message)
}
}
}
<input id="code">
<button onclick="doIt()">Check it</button>
For example, try the same things you tried before and see how this behaves.
If I understood your question correctly, the only thing you want to know is "Is that a valid expression". One very simple way to check this is using eval() as you did here, and to enclose it in a try, and see if any error occurs. For example, you could write this :
try {
eval('2+2(9.1-)9');
valid = true;
} catch (e) {
valid = false;
}
Then, the variable valid contains true if the expression is valid, and false if it is not.
Warning with eval() though : Every valid code will pass this test, not only mathematical expressions : Plus, that code will be executed. Be careful what strings you give it.
I have this javascript code which is not working.
function myfun()
{
return
{
alert("para");
}
};
myfun();
I have read about the javascript's automatic semicolon insertion. I corrected the above code as
return{
alert("para");
}
But still got the error : unexpected token (.
I wonder why?
NOTE: I don't need the solution but I need the explanation why the above code in not working.
EDIT
According to the book, javascript the good parts, the return statement if returns value must be in same line as return expression.
ie
return {
status: true
};
AND
return
{
status: true
};
Is wrong.Then How come
function myfun(para)
{
var status;
return
{
status : alert(para)
};
};
myfun("ok");
produce no error.It won't work but shows no error as well.It works when the { is in the same line as return.
ie
function myfun(para)
{
var status;
return{
status : alert(para)
};
};
myfun("ok");
In
return {
alert("para");
}
the {...} are interpreted as object literal. An object literal has the form
{
key: value,
//...
}
Object literals cannot contain arbitrary statements.
Looks like you've difficulties with ASI and the difference between run-time and parsing-time.
Where as
return {
status: true
};
is a correct way to return an object, ASI will take an action in the following code:
return
{ // ^-- ASI will insert a semicolon here
status: true
};
The semicolon is automatically inserted, and at run-time all lines after return are ignored. However, at parsing time, everything counts, and if there's a syntax error, like in your first example, an error will be thrown.
The reason why you are getting that error is because JS is expecting a value to the key "para".
There is no compulsion to return in a JavaScript function. If your intention is to test if the control goes to the function, you can simply change it to
function myfun() { alert("para"); }
if you want to return an object with string "para" you should change it to
function myfun() { return { "text": "para" }; }
I am new to javascript. I have two documents--an old and a new--that I am comparing. However, I am getting a syntax error somewhere in the code below.
Somewhere in here, my code is blowing up. The error says "expression does not eval to a function." Any syntactic ideas of where I'm writing an incorrect statement?
if(userCtx.name != oldDoc.Document.attributeA) {
for (var key in oldDoc.Document)
{
if(newdoc.Document.hasOwnProperty('key')
{
if(oldDoc.Document[key] != newDoc.Document[key])
{
if(key === 'attributeB')
{
return;
}
else
{
throw(forbidden: 'Only admins may change this field.')
}
}
}
}
}
if(newdoc.Document.hasOwnProperty('key') <-- I am missing a )
To throw an object literal, replace the round brackets with curly brackets:
throw {
forbidden: 'Only admins may change this field.'
};
Is the code you posted inside of a function definition? I've seen that error when defining functions that get passed as arguments to something else, and forgotten to wrap the function in parenthesis.
For example:
"compare": "function(docA, docB) { ... }"
should be:
"compare": "(function(docA, docB) { ... })"
And possibly one more...
Is this inside a function? If not you might be getting an error on the return;
I need to test whether the value of a form's onsubmit is a function. The format is typically onsubmit="return valid();". Is there a way to tell if this is a function, and if it's callable? Using typeof just returns that it's a string, which doesn't help me much.
EDIT: Of course, I understand that "return valid();" is a string. I've replaced it down to "valid();", and even "valid()". I want to know if either of those is a function.
EDIT: Here's some code, which may help explain my problem:
$("a.button").parents("form").submit(function() {
var submit_function = $("a.button").parents("form").attr("onsubmit");
if ( submit_function && typeof( submit_function.replace(/return /,"") ) == 'function' ) {
return eval(submit_function.replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?"); return false;
}
} );
EDIT 2: Here's the new code. It seems that I still have to use an eval, because calling form.submit() doesn't fire existing onsubmits.
var formObj = $("a.button").parents("form");
formObj.submit(function() {
if ( formObj[0].onsubmit && typeof( formObj.onsubmit ) == 'function' ) {
return eval(formObj.attr("onsubmit").replace(/return /,""));
} else {
alert("onSubmit is not a function.\n\nIs the script included?");
return false;
}
} );
Suggestions on possibly how to do this better?
I'm replacing a submit button with an
anchor link. Since calling
form.submit() does not activate
onsubmit's, I'm finding it, and
eval()ing it myself. But I'd like to
check if the function exists before
just eval()ing what's there. – gms8994
<script type="text/javascript">
function onsubmitHandler() {
alert('running onsubmit handler');
return true;
}
function testOnsubmitAndSubmit(f) {
if (typeof f.onsubmit === 'function') {
// onsubmit is executable, test the return value
if (f.onsubmit()) {
// onsubmit returns true, submit the form
f.submit();
}
}
}
</script>
<form name="theForm" onsubmit="return onsubmitHandler();">
<a href="#" onclick="
testOnsubmitAndSubmit(document.forms['theForm']);
return false;
"></a>
</form>
EDIT : missing parameter f in function testOnsubmitAndSubmit
The above should work regardless of whether you assign the onsubmit HTML attribute or assign it in JavaScript:
document.forms['theForm'].onsubmit = onsubmitHandler;
Try
if (this.onsubmit instanceof Function) {
// do stuff;
}
You could simply use the typeof operator along with a ternary operator for short:
onsubmit="return typeof valid =='function' ? valid() : true;"
If it is a function we call it and return it's return value, otherwise just return true
Edit:
I'm not quite sure what you really want to do, but I'll try to explain what might be happening.
When you declare your onsubmit code within your html, it gets turned into a function and thus its callable from the JavaScript "world". That means that those two methods are equivalent:
HTML: <form onsubmit="return valid();" />
JavaScript: myForm.onsubmit = function() { return valid(); };
These two will be both functions and both will be callable. You can test any of those using the typeof operator which should yeld the same result: "function".
Now if you assign a string to the "onsubmit" property via JavaScript, it will remain a string, hence not callable. Notice that if you apply the typeof operator against it, you'll get "string" instead of "function".
I hope this might clarify a few things. Then again, if you want to know if such property (or any identifier for the matter) is a function and callable, the typeof operator should do the trick. Although I'm not sure if it works properly across multiple frames.
Cheers
What browser are you using?
alert(typeof document.getElementById('myform').onsubmit);
This gives me "function" in IE7 and FireFox.
using a string based variable as example and making use instanceof Function
You register the function..assign the variable...check the variable is the name of function...do pre-process... assign the function to new var...then call the function.
function callMe(){
alert('You rang?');
}
var value = 'callMe';
if (window[value] instanceof Function) {
// do pre-process stuff
// FYI the function has not actually been called yet
console.log('callable function');
//now call function
var fn = window[value];
fn();
}
Make sure you are calling typeof on the actual function, not a string literal:
function x() {
console.log("hi");
}
typeof "x"; // returns "string"
typeof x; // returns "function"
You can try modifying this technique to suit your needs:
function isFunction() {
var functionName = window.prompt('Function name: ');
var isDefined = eval('(typeof ' + functionName + '==\'function\');');
if (isDefined)
eval(functionName + '();');
else
alert('Function ' + functionName + ' does not exist');
}
function anotherFunction() {
alert('message from another function.');
}
form.onsubmit will always be a function when defined as an attribute of HTML the form element. It's some sort of anonymous function attached to an HTML element, which has the this pointer bound to that FORM element and also has a parameter named event which will contain data about the submit event.
Under these circumstances I don't understand how you got a string as a result of a typeof operation. You should give more details, better some code.
Edit (as a response to your second edit):
I believe the handler attached to the HTML attribute will execute regardless of the above code. Further more, you could try to stop it somehow, but, it appears that FF 3, IE 8, Chrome 2 and Opera 9 are executing the HTML attribute handler in the first place and then the one attached (I didn't tested with jQuery though, but with addEventListener and attachEvent). So... what are you trying to accomplish exactly?
By the way, your code isn't working because your regular expression will extract the string "valid();", which is definitely not a function.
If it's a string, you could assume / hope it's always of the form
return SomeFunction(arguments);
parse for the function name, and then see if that function is defined using
if (window[functionName]) {
// do stuff
}
Isn't typeof xxx === 'function' the best and the fastest?
I made an bench in wich you can try it out, compared to instanceof and _underscore
Its just seems to be faster than instanceof (using chrome)
It won't trow an error if the variable is not defined
Here a bench: https://jsbench.me/qnkf076cqb/1
Checking the call method on the value seems to be a good enough test. e.g., val.call && val()
> a = () => {}
[Function: a]
> function b() {}
undefined
> c = function(){}
[Function: c]
> d = 2
2
> e = []
[]
> f = {}
{}
> a.call
[Function: call]
> b.call
[Function: call]
> c.call
[Function: call]
> d.call
undefined
> e.call
undefined
> f.call
undefined
Note: Except when it's a class.
Well, "return valid();" is a string, so that's correct.
If you want to check if it has a function attached instead, you could try this:
formId.onsubmit = function (){ /* */ }
if(typeof formId.onsubmit == "function"){
alert("it's a function!");
}
You can always use one of the typeOf functions on JavaScript blogs such as Chris West's. Using a definition such as the following for the typeOf() function would work:
function typeOf(o){return {}.toString.call(o).slice(8,-1)}
This function (which is declared in the global namespace, can be used like this:
alert("onsubmit is a " + typeOf(elem.onsubmit));
If it is a function, "Function" will be returned. If it is a string, "String" will be returned. Other possible values are shown here.
I think the source of confusion is the distinction between a node's attribute and the corresponding property.
You're using:
$("a.button").parents("form").attr("onsubmit")
You're directly reading the onsubmit attribute's value (which must be a string). Instead, you should access the onsubmit property of the node:
$("a.button").parents("form").prop("onsubmit")
Here's a quick test:
<form id="form1" action="foo1.htm" onsubmit="return valid()"></form>
<script>
window.onload = function () {
var form1 = document.getElementById("form1");
function log(s) {
document.write("<div>" + s + "</div>");
}
function info(v) {
return "(" + typeof v + ") " + v;
}
log("form1 onsubmit property: " + info(form1.onsubmit));
log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit")));
};
</script>
This yields:
form1 onsubmit property: (function) function onsubmit(event) { return valid(); }
form1 onsubmit attribute: (string) return valid()
// This should be a function, because in certain JavaScript engines (V8, for
// example, try block kills many optimizations).
function isFunction(func) {
// For some reason, function constructor doesn't accept anonymous functions.
// Also, this check finds callable objects that aren't function (such as,
// regular expressions in old WebKit versions), as according to EcmaScript
// specification, any callable object should have typeof set to function.
if (typeof func === 'function')
return true
// If the function isn't a string, it's probably good idea to return false,
// as eval cannot process values that aren't strings.
if (typeof func !== 'string')
return false
// So, the value is a string. Try creating a function, in order to detect
// syntax error.
try {
// Create a function with string func, in order to detect whatever it's
// an actual function. Unlike examples with eval, it should be actually
// safe to use with any string (provided you don't call returned value).
Function(func)
return true
}
catch (e) {
// While usually only SyntaxError could be thrown (unless somebody
// modified definition of something used in this function, like
// SyntaxError or Function, it's better to prepare for unexpected.
if (!(e instanceof SyntaxError)) {
throw e
}
return false
}
}
if ( window.onsubmit ) {
//
} else {
alert("Function does not exist.");
}
Beware that es6 class is also a function but not callable
class C {}
typeof C === "function" // true
C instanceof Function // true
C() // error
C.call() // error
new C() // okay
new C // okay
A simple check like this will let you know if it exists/defined:
if (this.onsubmit)
{
// do stuff;
}