As part of a homework I am trying to implement a JavaScript console similar to the one available in Firebug in a browser environment. From what I've picked up, eval() seems to be the easiest way to do this. However, my code runs into some problems on even very basic user input. For example:
var number = 5;
Causes a syntax error rather than just evaluating to undefined like it would in Firebug. Because of this I can't seem to declare variables at all inside the eval string. If I do something more simple like:
3 + 4 * Math.PI
It works correctly. I have tried to find an example of someone using eval() on a string containing a variable declaration, and I just can't seem to find anyone doing this.
Do I need to parse the user input completely using regular expressions before compiling it into a new string for eval()?
Can eval() understand semicolons as line breaks? I can't find people using these either.
function runMiniFirebug() {
var userInput = document.getElementById("user-input").value;
try {
var userOutput = eval('(' + userInput + ')');
document.getElementById("js-output").innerHTML += '<p class="input">>>>' + userInput + '<p>';
document.getElementById("js-output").innerHTML += '<p class="ouput">' + userOutput + '<p>';
}
catch(error) {
document.getElementById("js-output").innerHTML += '<p class="input">>>>' + userInput + '<p>';
document.getElementById("js-output").innerHTML += '<p class="error">' + error.message + '<p>';
}
}
EDIT:
So it seems the added parens are causing the error. This is a section from my instructors slides. Is the information incorrect, or am I just interpreting it incorrectly?
Strings that are delimited with { ... }
– You have to add extra parens so that JavaScript will know that the
braces are for object literals, not for delimiting statements.
• It never hurts to do this, so add parens routinely
– var test2 = "{ firstName: 'Jay', lastName: 'Sahn' }";
– var person = eval("(" + test2 + ")");
var userOutput = eval('(' + userInput + ')');
Why are you wrapping with parentheses? This creates the statement
(var number = 5;)
which is invalid syntax.
Simply remove the '(' + and + ')'.
As for your edit, that is referring to only evaluating single expressions. var number = 5; is not an expression, nor is alert(1 + 1); alert(2 + 2);. Wrapping either in parentheses will cause an error.
Related
So basically what I'm trying to do is print a simple string to the screen using the console.log function.
Here's an example :
const fromLabel: string = '["' + "AppExp" + '"]' + '\n' + '["' + "AppExp" + '"]';
And I ultimately wanna print it, so I go:
console.log(fromLabel);
and my output is:
[\"AppExp\"]\n[\"AppExp\"]
So, basically no carriage return and unwanted '\'.
Any idea what could be the problem?
EDIT: Never mind. I was working with objects and to print them I used JSON.stringify.. little did I know I used it on this string as well ..my bad
Backslashes are escaping certain characters in the string. Your string is put together in a weird way—you're mixing "" and ''. Try this:
var str = '["' + 'AppExp' + '"]' + '\n' + '["' + 'AppExp' + '"]'
console.log(str)
try this code with template literals
I omitted the : string to be able to run the snippet but remember to add it!
const fromLabel = `[""AppExp""]
[""AppExp""]`;
console.log(fromLabel);
or in case you do not want duplicate " chars
const fromLabel: string = `["AppExp"]
["AppExp"]`;
I hope it helps! :)
How do I create a dynamic variable in Javascript?
For example, I have:
var myAwesomeText = "Hello World!"
But now I want the varible MyAesomeText to have a random number attached to it every time the page is refreshed. So it would instead look like something like this:
var myAwesomeText12345 = "Hello World!"
And most importantly, how do I call that that new random variable back once the random number has been assigned to it? (i.e: alert(???);)
I've tried something like this, but I'm going wrong with this somewhere.
var myRnd = Math.floor(Math.random()*100000);
var myVar = "MyAwesomeText" + myRnd;
str = myVar + ' = ' + '"Hello World!"';
eval(str);
alert(str);
You can access the variable via the window object:
var myRnd = Math.floor(Math.random()*100000);
var myVar = "MyAwesomeText" + myRnd;
window[myVar] = "Hello World!";
alert(window[myVar]);
Don't use eval for this: it is slower and completely unnecessary for this problem. Also it can have unexpected side-effects if your MyAwesomeText has characters in it that have special meaning in JavaScript code, such as brackets, semi-colon, colon, comma, braces, ... etc.
Note that the notation object['prop'] gives the same result as object.prop. Since global variables are created in the window object, you can access any variable via the window.myvariable notation.
Combining these two facts, you can access global variables that have a dynamic name with window[dynamicVariableName].
eval is the way to go
var num = 10;
var string = "var a"+num +"= 'hi'"
string
// "var a10= 'hi'"
eval(string)
a10
// 'hi'
You miss one eval on the alert
var myRnd = Math.floor(Math.random()*100000);
var myVar = "MyAwesomeText" + myRnd;
str = myVar + ' = ' + '"Hello World!"';
eval(str);
alert(eval(myVar));
function expand(element) {
var target = document.getElementById(element);
var h = target.offsetHeight;
var sh = target.scrollHeight;
var loopTimer = setTimeout('expand(\'' + element + '\')', 10);
if (h < sh) {
h += 1;
} else {
clearTimeout(loopTimer);
alert("伸縮完成");
}
target.style.height = h + "px"
}
\' is an escape character for ', so what this is doing is building a string that can be consumed as a function, which contains a parameter, which is wrapped in single quotes...
'expand(\''
The above portion "opens" the string, applies expand( as a literal, then an escaped ', followed by one more ' to close that portion of the string. So, the return on that is:
expand('
Next, they concatenate the value of element variable:
'expand(\'' + element
The string now contains:
expand('elementVariableValue
Next up is to open another literal string, add in another single quote (escaped), followed by the closing parenthese:
'\')'
this is evaluated to:
')
put it all together and you get:
expand('elementVariableValue')
(which is finally interpreted as a function for the timeout).
Now, with JavaScript, you can use both " and ' for string delimiters, so much easier might have been:
setTimeout("expand('" + element + "')", 10);
Code in your example is a recursive call. It's a timer and the callback is expand(element). Understand this, you can easy understand that var loopTimer = setTimeout('expand(\'' + element + '\')', 10); means another call to expand(element). However, function expand need a string parameter, so \'' + element + '\' it is. Finally, if element here equals to scaleid, we finally get expand('scaleid'), it is obviously another call to expand(). Cause it is in string, so \' is needed to escape it.
In Javascript you can pass as the first parameter of the function a string, this string is evaluated as if you use eval(). That code is like if you call the function expand("something") every 10 milliseconds.
I’m loading the contents of a JS file using FileReader and dumping the results into a textarea container. I then want to run some checks on the actual JS file.
I know there are probably tools out there for this already (or better ways), but this is for a closed-environment project.
After the textarea contains the content of the JS file as one large string, I need to loop the string and find all instances of parseInt() to check if they have been supplied with a radix.
I would provide code, but I have nothing working at this point. Any ideas?
The following snippet will search the string value of your <textarea> element for parseInt() and output the occurences, with radix where applicable:
var textareaValue = 'var func = function(){' +
'var i = parseInt(1,1);' +
'var j = parseInt(10, 10);' +
'var k = parseInt(3) + j;' +
'};';
occurences = textareaValue.match(/parseInt\(.+?(, ?\d+)?\)/g);
occurences.forEach(function(occurence){
var hasRadix = /, ?\d+\)$/.test(occurence);
document.body.innerHTML += '<p>"' + occurence + '" has ' +
(hasRadix ? 'a' : 'no') + ' radix' +
(hasRadix ? ' (' + occurence.match(/, ?(\d+)\)$/)[1] + ')' : '') +
'.</p>';
});
Note that this is no actual syntax interpretation, it’s merely text analysis. You will have to go from the result, which comprises all the occurences of parseInt() as strings. Also, JavaScript allows whitespace, comments, expressions and other witchcraft at the text passage in question. You might to have to check for anything.
The actual regex /parseInt\(.+?(, ?\d+)?\)/g will demand…
parseInt( at the beginning of the match
any characters (might need to be expanded to include brackets, etc. by :punct:)
as optional group, determining whether a radix is supplied or not:
a comma, an optional space (might need to respond to any number of whitespace using *)
at least one digit (might need to limit to {1,2}, because only 2 to 36 are valid)
a trailing closing bracket.
The following function should be able to tell the difference between usages of parseInt with radix versus its usages without radix by simplistic regex matching:
function have_radix(str){
parseIntRegex = /parseInt\(.+?\)/g;
parseIntRegexWithRadix = /parseInt\(.+?(,.+?\))/g;
indices = [];
while ( (result = parseIntRegex.exec(str)) ) {
indices.push(result.index);
}
count = indices.length;
indices = [];
while ( (result = parseIntRegexWithRadix.exec(str)) ) {
indices.push(result.index);
}
diff = count - indices.length;
return diff;
}
My input is many lines of text that looks like this:
a.b.c.d.e (f:g)
I need to turn this into
a.b.c.d.e (a/b/c/d/e/f?g)
Note that the dotted part (a.b.c.d.e) can have varying numbers of elements, so sometimes it'll be q.r.s.t, sometimes u.v.w.x.y.z and so on. I have a replace() that will give me (a.b.c.d.e.f?g), but what I need is then to turn all those .s into /s in the result.
Is there a way to do a replace inside a replace? Or should I just call replace() on the string twice?
Sorry if this question is poorly worded, I'm not awfully well versed at regular expressions in javascript.
A very crazy way of doing it:
var str = "a.b.c.d.e (f:g)";
var re = /([^\s]+)\s\(([^:]+):([^\)]+)\)/;
var newStr = str.replace(re, function(a,b,c,d){ return b + " (" + b.replace(/\./g,"/") + "/" + c + "?" + d + ")"; });
jsfiddle
You need to chain the calls to replace() one after the other.
var result = source.replace("foo", "bar").replace("oof", "rab");
A saner way :) http://jsfiddle.net/smfPU/
input = "a.b.c.d.e.w.x.y.z (f:g:h)";
output = input.replace(/:/g, "?");
outputparts = output.split("(");
left = outputparts[0];
middle = left.replace(/\./g, "/").trim();
right = outputparts[1];
output = left + "(" + middle + "/" + right;
document.write(output);