Converting `eval` statements to functions (implicit return) - javascript

I have developed a large number (>1000) strings that are intended to be fed into eval. I am trying to migrate away from using eval, as "eval is evil" and I'm generally trying to make things more secure. However, migrating from eval into a properly defined function is a little tricky, as eval() returns the value of the last expression evaluated. This means that a string that was previously evaled like this:
const stringToEvaluate = "x = 1; x + 1"
is difficult to migrate directly into a function, because the last expression in the statement does not explicitly return anything.
With regards to the string above, I might use eval in this way:
const y = eval(stringToEvaluate)
console.log(y) // 2
However, I can't use:
const y = (function safeFunction() {
x = 1;
x
})()
console.log(y) // undefined
as safeFunction does not return anything.
Importantly, I am looking for a way to migrate these eval strings without needing to modify each individual string to include return statements in appropriate places. This is because the large number of scripts would make this quite inconvenient. Also, the scripts can be more complicated than this, but this is a nice, minimal example.
Does anyone happen to know of any way to migrate these scripts into functions without needing to manually edit each of them? Also, this is one my first times posting to StackOverflow, so I welcome any feedback about ambiguity in my question! Thanks!
Edit:
Apologies for the ambiguity, another example of a "string" to be converted into a script is:
const stringToEvaluate = """
let x;
if (
$('.itemToFind').length > 0 &&
$('.itemToFind').html().trim() != ''
)
$('.itemToFind del').html().trim(); <<< eval wraps either this
else if ($('.price h4.offer-price').length > 0)
$('.itemToFind').html().trim(); <<< or this
"""
(note that I have included the string across multiple lines to aid readability).

Related

How do I re-assign the else if in javascript to function the same but typed as elif?

I'm currently doing some JavaScript programming and don't like having to type else if everytime I need to use it. I would much rather just type elif. I have done tons of research and don't know how I could get something like this... look at code ... to work where I can still say elif, but it is recognized as else if and I would be able to use it without the program.
elif = else if;
let x = 20;
if (x >= 21) {
console.log('psych bwah!');
} elif (x <= 19 ) {
console.log('umm... nope try again bud!');
} else {
console.log('ladies and gentlemen we gotem!');
}
I really want this to work so badly. And it would be so mind pleasing to understand how to rewrite pre-made code in terms that I want to use. Another example of what I'm trying to accomplish would be re-assigning the console.log() printing function to something shorter but still does the exact same thing, maybe c.l() as a shorter version, just for example though.
Having the ability to assign already usable normal JavaScript code to my own version of code is the task I guess I am trying to accomplish, if that makes sense. This way I can shorthand it and make everything way faster than I'd be able to before. So what I am really looking for is a better/working way, because my current method seen above in the code doesn't work, is maybe some form of a method or other way of changing the name of an if...else keeping the same function just typed/said different in code.
Answer:
Yes, it's possible.
As a note, it's not a great idea to do this for any production projects for a multitude of different reasons, however, it's a rather simple process for toy code or snippets.
How:
You can create a text/template script tag, parse it for Regular Expressions or Plain Text - just like any other String - replace it with whatever you would like, then place it in a Function constructor and call it.
A longer explanation I wrote in an article a while back can be found here: https://medium.com/wdstack/understanding-javascript-micro-templating-f37a37b3b40e
A larger example with a couple of different code adjustments ( for instance instead of if(a === b || a === c) you can write if(a === b || c) ) can be found here: https://codepen.io/zfrisch/pen/ENpvOq
Basic example of Elif:
var scriptText = document.querySelector('#microTemplate').innerText,
parsed = scriptText.replace(/elif/g, "else if"),
fn = new Function(parsed);
fn();
<script id="microTemplate" type="text/template">
let a = 5;
if(a < 5) console.log("a is less than 5");
elif(a === 5) console.log("a is 5");
else console.log("a is greater than 5");
</script>
NOTE Keep in mind these examples aren't filled with full-proof Regular Expressions. This is just a bare-bones example of how you can do simple transpiling. For instance if you put a string in the above code with "elifant" it will write "else ifant".
Conclusion
I don't know if I've stressed this enough, haha, but seriously do NOT use this in Production. :)
In any case I hope this trick helped answer your question! Happy Coding!
You can't assign a statement to a variable, you can only assign an expression.
if,else, and else if are all statements (along with try/catch, switch, for, while, etc..)
So in short, there is no real way that bit can work.
To alias an existing function you simply assign the existing function to a new variable, like so:
const c = {}
c.l = console.log
c.l('console','.','log','arguments')

decode javascript sequence into python

I'm a beginner to Python trying to decode this javascript sequence. I'm not only a beginner in Python, I understand javascript even less :) I know i could put it into an online decoder such as this: http://coderstoolbox.net/string/ but I want to deal with it myself - more for practice than anything else... Im using Beautiful Soup to get the data, so I have its functions available for decoding.
If anyone can point me to equivalent functions in python I would appreciate it.
function encode(str){
var t=''; var s=unescape(str);
var x=Math.round(Math.sqrt(49));
for(var i=0;i<s.length;i++) t+=
String.fromCharCode(s.charCodeAt(i)^(i%2?x:0));
print(t);
}
This is my understanding of it so far:
i think I can use 'HTML entities in BS to unescape..?
the second one just seems to be a constant number ? square root of 49 rounded...
sets up the loop
this is the one i dont get. 1 i dont know what the fromCharCode function does. 2 not sure what the bit at the end is. looks like its getting a character code from i to the power something. i understand i is being modulo'd with 2 but what is the '?x:0' bit ? - how would you replicate this in Python ?
thanks for reading !
EDIT: is there a python library that can just run this code ? I've done this before with bash and used rhino, but the alternatives in Python seem a bit scary for a beginner, eg spidermonkey, etc...
1) the python equivalent to unescape is urllib.unquote() in python 2.x series and urllib.parse.unquote() in python 3.x series
2) you guess the simplest way to do it is to do x = 7
3) the simplest way to loop on string charters is to do for c in string: but to have the index you should do for i,c in enumerate(string):
4) the string.charChodeAt(c) is the same than chr(c)
finally I would duplicate the loop part as follow:
result = []
for i,c in enumerate(string):
result.append(chr(ord(c)^(x if i%2 else 0)))
print("".join(result))
in fact using a temporary array to make the appends is more efficient than happening to strings as the strings don't mutate
I don't know Python, but I can explain what is happening here so that you can rewrite in Python.
1) function encode is declared and not assigned, so in JavaScript it will get hoisted to the top of its parent function, if there is one.
2) Inside function encode there are 4 variables that will get hoisted to the top of function encode:
t, which is assigned to an empty string, which means 0 length but type is string
s, which is assigned of a value of the argument "str" that is passed through the unencode function. unencode just reverses a URI reserved character encoding.
x, which is of type number with a value of 7
i, which is assigned 0 and used as your loop iterator
3) The loop index starts at 0 and breaks no later than the index is the same size as the character length on variable s.
4) The loop is written in a sloppy manner without curly braces, so it terminates at the first line break, which means variable t is performing a string concat in reflection of variable s.
5) The next line beginning with the string object looks like it is supposed to be in loop, but its not, because this code is sloppy. It doesn't matter anyways because variable s is not really used for anything further.
6) A print function is used with variable t as its argument. Variable t should look identical to variable s, which is probably not what the original author of this code intended.
7) I have no idea what print is. Perhaps the original author meant something like alert or console.log instead of print.

Does it make any sense to use JSLint and follow it? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Lately I've been writing some JS code using jQuery and JavaScript as it is and I thought I will give JSLint a try. Let me say that the code contains various functions and jQuery usages and it works fine (without any errors ) in IE8 and latest Firefox.
The code also validatas as XHTML 1.0 Transitional (and Strict too but I mostly want it to be Transitional valid).
However, with JSLint it's like everything is wrong. While I have read about it being very strict, even if I turn on only "The Good Parts" it's still like 70+ errors in a typical HTML page.
It starts out with this (why in the world would I want to remove the type to make my documents XHTML invalid??)
Problem at line 5 character 67: type is unnecessary.
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
and goes on with esoteric errors like
Problem at line 41 character 41: Use the array literal notation [].
var rows = new Array();
Problem at line 42 character 30: Too many var statements.
for (var i = 0; i < data.length; i++) {
Problem at line 42 character 55: Unexpected use of '++'.
for (var i = 0; i < data.length; i++) {
Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.
var item = $("#item_" + data["PrettyId"]);
If anyone can provide me answers to these errors and especially, how to make JSLint be aware of jQuery and understand it, I will appreciate it.
If not, please explain whether you use it or not and whether you advice to use it or not.
UPDATE:
I'm going to wait one more day for more answers, if any, then I'll accept the answer with the most upvotes.
A thing to remember when using JSLint is that is built on the opinion about what one person thinks is the "Good Parts".
I think is a great tool but there are rules that I don't agree with.
About the type attribute, you can find more about the opinion of the author here he says that the attribute is "required and non necessary", but if you validate your documents you clearly need it.
With the use of the Array literal notation [] vs. the Array constructor, I agree, there are differences that can make the two syntaxes behave different, for example:
[5]; // one-element array
["5"]; // one-element array
new Array(5); // empty array but its length is initialized with 5
new Array("5"); // one-element array
So, for consistency an brevity the literal notation is better.
About the "Too many var statements", JavaScript has no block-scope, the scope is at function or global level, and all var statements are evaluated before the code execution -aka hoisting- and they are initialized with undefined, while the assignments are made at runtime.
For example:
var x = 0;
if (true) {
var x = 1; // useless var, x already declared
}
x; // 1
And the "hoisting" of variable declaration can be shown in this example:
var x = 5; // global
(function () {
alert(x); // alerts `undefined`, x declared but unassigned in this scope
alert(y); // ReferenceError, y is undeclared
var x = 10;
})();
As you can see x holds undefined because it is declared before the actual code execution, the var statements are hoisted to the top of their enclosing scope:
var x = 5; // global
(function () {
var x;
alert(x); // alerts `undefined`, x declared but unassigned
alert(y); // ReferenceError, y is undeclared
x = 10; // assignment is made
})();
So that rule wants to actually make the code to resemble what will happen, all the var statements at first place.
About the "Unexpected use of '++'", this is another rule that I don't quite like, the author thinks that "those contribute to bad code by encouraging excessive trickiness".
When I use them in some expression, I try to extract the operator usage to an alone statement, for example:
array[++id] = x;
To:
id+=1;
array[id] = x;
Which is more clearer, but anyway in the case of a for statement IMO it can't cause any confusion at all...
About the last one "['PrettyId'] is better written in dot notation.", JSLint expects the usage of the bracket notation to be "dynamic", it expects to see an expression there, not a String literal that contains a valid identifier name, the bracket notation should be used only when you want to access a property with a name that clashes with a reserved word e.g.:
data.function; // SyntaxError in ECMAScript 3 based implementations
data["function"]; // Ok
Or when a property contains characters that are not a valid identifier, e.g.:
data.foo-bar; // it access the property `foo` minus a `bar` variable
data["foo-bar"]; // Ok
data.foo bar; // SyntaxError, unexpected `bar` identifier
data["foo bar"]; // Ok
I use jslint on .js files and find a combination of options and fixes to make it happy. I find it improves my code quality. I would recommend running it, even if you only use it to isolate omitted 'var' declarations.
I avoid the script tag warning by not running against html files. I use jslint systematically on .js files, but not on html. I find it is just too burdensome to declare all the global identifiers that got defined in included scripts, but aren't visible to jslint.
Crockford's book 'Javascript: The Good Parts' explains many if not all of the jslint warnings, and some of them are based on perceived bug proneness. The 'new Array()' vs ' []' warning is based on Doug's aversion to the 'new' operator. Omitting 'new' for various constructors is commonly valid code, but not correct code, and using the alternative syntax avoids that risk.
The 'too many vars' error means just that, a large number of 'var' declarations in a given function: the Crockford endorsed style is to use one or very few 'var' declarations, all at the top of the function. You can declare multiple variables in one var statement, by separating them with commas.
The '++' caution is another bug proneness based warning; Using '+=1' means the same thing, and Doug believes it to be less error prone.
jslint is thus a mixed bag. Some features (locals vs globals) are invaluable, some (script types) are just annoying, and many are of dubious benefit but harmless.
jQuery itself passes jslint checks, as described here:
http://docs.jquery.com/JQuery_Core_Style_Guidelines#JSLint
There's an old joke about a programmer who smoked. A friend said, "You're a really smart guy, can't you read the warning on the pack that says cigarettes will kill you?" Came the reply: "I'm a programmer. We only pay attention to errors, not warnings."
Sometimes JSLint tells you things that are critical, sometimes it just nags. You can get lost trying to make it happy, but you might just be lost without it. Like any other tool, its input should be taken with a grain of salt. I prefer to think of it like the spell-checker or grammar-checker in MS Word. Sometimes it's right, sometimes it's wrong, and sometimes I just don't care what it tells me.
It hurts when you start using it on your old code.
But then it will save you a lot of time.JSLint can detect many problems that you would only see when refreshing your page or worse when your users do.Now it hurts me when I have to use an editor without JSLint
Another advantage is when you start compressing your javascript. If you pass the JSLint checks, you are almost certain to compress without problems.
That being said, jquery has 23 warning, most of them about regex, but is widely used without any problems.
JSLint is a Code Quality tool. It's not like W3C validator. Consider it something like a weekly code review at a company. Coding conventions vary and JSLint is just one of them. There may be points you don't agree with, but if you work in a team and you need to manage a larger codebase JSLint can be a life saver. Why? Because it warns you about things that are confusing or error prone.
The best way to use JSLint is this: read everything it says and if you're unsure about something correct it as suggested (as it seems to be the case here).
The reason is that JSLint is meant to avoid confusion and if you're using something that can lead to errors and you don't know why, then you better off with a clear alternative.
And if you want to know the reasoning behind the suggestions watch Douglas Crockford's videos on Javascript.
Finally, you can turn off filters that you find useless.
you should use it. The fact that it works in one browser doesn't mean it will work in all browsers; some are more lenient than others. for example, having a trailing comma in an array will break in IE but work in FF.
Be aware that sometimes you get a ton of errors, but you remove the first and a dozen go away, like compiling code.
you can do
var rows = [];
for the first error.
Here are the best answers I can give. Perhaps someone can fill in some blanks. It doesn't appear as though any of these relate to jQuery, though.
Also, see this document for some explanations.
Problem at line 5 character 67: type is unnecessary.
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
and goes on with esoteric errors like
I believe that for modern browsers, there's no need for text/javascript when linking to external js files.
Problem at line 41 character 41: Use the array literal notation [].
var rows = new Array();
It is recommended to not call the constructor when creating an Object or Array. I'm honestly not sure why. Anyone?
Problem at line 42 character 30: Too many var statements.
for (var i = 0; i < data.length; i++) {
I suppose you have the i variable declared elsewhere in the same scope. A javascript block does not create scope, so if you have another for loop (for example) that uses i, it is using the same variable. No need to declare it again.
Problem at line 42 character 55: Unexpected use of '++'.
for (var i = 0; i < data.length; i++) {
Not sure about this one, except that if I recall correctly, Crockford doesn't like the ++ and --.
Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.
var item = $("#item_" + data["PrettyId"]);
I believe . notation is preferred because it is shorter and faster (in some browsers anyway). So data.PrettyID instead.
As far as I can tell, nothing here appears to be explicitly wrong. Mostly just best practice advice from JSLint creator's perspective.

Shortest way of creating a "new function" alias in javascript

What's the shortest way (characters) of creating a "new function" alias.
Basically this is for code golf and minifying code beyond reason.
So when you usually would write:
a=function(a,b,c){return a+b+c;}
You could write something like (also let's abstract return keyword as well with global variable R):
a=$("a,b,c","R=a+b+c")
a=$(a,b,c){R=a+b+c}
(Not sure if the second one is possible.)
For the first example the best I've come up with is:
$=function(a,b){return new Function(a,"R=0;"+b+";return R")}
Both the sizes (usage, declaration) matter but usage size is more important.
I don't think new Function() is of viable use for most functions even without performance concerns because unlike function() {} no closure is created. The compiled function will only have access to its own local scope and the global object. Think about that for a second. Javascript without closures is like Java without classes or C without pointers. Clearly everything would break.
Anyways, if you only intend to use this alias for short lambada like expressions that don't need clousers, one obvious way to make things even more terse is to leave off the parameters deceleration. Simply assume that a = arguments[0]; b = arguments[1]; etc...
$=function(b){return new Function('a,b,c,d,e,f,g,h,i,j', b);};
Another way would be to automatically return the value of the last expression, instead of needing it to be explicitly declared
$=function(body) {
return function(a,b,c,d,e,f,g,h,i,j) { return eval(body); };
};
Horrifying isn't it? This works because eval()...well it returns the value of the last evaluated expression. No return needed. Of course this method is an even bigger hit to performance, as the code in body is reevaluated each time the function is called, while with new Function the code is (or should be) only compiled once.
Anyways performance be dammed, with the previous method your function declaration is down to this
var myeyes = $('a+b+c');
alert(myeyes(1,2,3)); //6
Purdy huh? Still, I think it would look better like this
'a+b+c'
Looks like a string yes? Well...it is a sting, but in the hands of the right function, it could be evaluated as if it were a full on function literal
//Lets just assume that IE does not exist mmkay?
var funcs = ['map', 'filter', 'every', 'some'];
for (var i=0; i<funcs.length; i++) {
(function() {
//Store original function
var name = funcs[i]
var _super = Array.prototype[name];
Array.prototype[name] = function() {
//$ !== jQuery
if (typeof arguments[0] == 'string') arguments[0] = $(arguments[0]);
return _super.apply(this, arguments);
};
}());
}
Now you can write
[1,2,3,4,5].map('a*a');
instead of
[1,2,3,4,5].map(function(a){return a*a;});
which is even better than Firefox's Expression Closure
[1,2,3,4,5].map(function(a) a*a);
Try it out here: http://jsbin.com/iyogu3/edit
If only we could actually write function expressions like this without calling upon the eval monster. Really, one of my main gripes with Javascript syntax is the requirement to spam function(){} throughout your code. Some kind of shorthand function literal syntax (not the aforementioned half-assed expression closure) that was interpreted the same as a regular verbose function literal would go a long way to making my code look a little less ridiculous. And it might help minifying a tiny bit as well.
For simple expressions, you could use:
function L(a,x){return new Function(a,'return '+x)}
Usage:
n=L('a,b,c','a+b+c');
You might get milage out of something silly like:
eval("t=Fa+b};t(1,2)".replace("F", "function(a,b){return "))
Here's a variant that has a larger overhead but saves one character per function definition.
"#" will be replaced with "return ".
$=function(a,b){return new Function(a,b.replace(/#/g,"return "))}
a=$("a,b,c","#a+b+c")
Your code:
a=function(a,b,c){return a+b+c;}
Shortened code:
a=(a,b,c)=>a+b+c
The shortest function declaration possible in js is 4 characters
Example: _=>1

What does "with" do in JavaScript?

I saw JavaScript code which begins with with. That's a bit confusing. What does it do and how can it be used correctly?
with (sObj) return options[selectedIndex].value;
It adds to the scope of the statements contained in the block:
return sObj.options[selectedIndex].value;
can become:
with (sObj)
return options[selectedIndex].value;
In your case, it doens't do a whole lot...but consider the following:
var a, x, y;
var r = 10;
a = Math.PI * r * r;
x = r * Math.cos(PI);
y = r * Math.sin(PI /2);
Becomes:
var a, x, y;
var r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
...saves a couple of keystrokes. The Mozilla documentation actually does a pretty good job of explaining things in a little more detail (along with pros and cons of using it):
with - Mozilla Developer Center
the with statement is pure syntactical sugar, but it also can cause some nasty bugs.
See with Statement Considered Harmful for clarification:
If you can't read a program and be confident that you know what it is going to do, you can’t have confidence that it is going to work correctly. For this reason, the with statement should be avoided.
In that with block you dont have to type:
sObj.options[selectedIndex].value
but you can just use:
options[selectedIndex].value
Its the equivalent of
return sObj.options[selectedIndex].value;
With lets you issue a block of statements in the context of a particular object. Therefore all of the statements in the with block are taken to be members of the object in parenthesis.
This can make code more readable at times, but it also can lead to ambiguity, since the variable references can either be with sObj or global.
legitimate uses for javascript's "with" statement :D
I would recommend NOT using this because of performance issues, but what the above means is:
for the object sObj (here presumably a select element), all children and properties referenced on this one (or between following curly braces) treat that as their parent scope.
Your example could be rewritten as...
return sObj.options[selectedIndex].value;
...as the 'with' statement places all related statements in the scope of the supplied object. In this case, it's pretty pointless but, if you were doing lots of operations on 'sObj', then it saves a lot of typing.
Totally ficticious example..
with (sObj)
{
if(options[selectedIndex].value < 10){
options[selectedIndex].value++;
total+ = options[selectedIndex].value;
}
}
But, having said that, it's often the case that saving typing can be achieved in better ways.
It isn't a function (as was indicated in the question title before it was edited) but a statement. It may make more sense if the code sample is formatted like so:
with (sObj){
return options[selectedIndex].value;
}
Regarding what it does (Source)
The with statement establishes the default object for a set of statements. JavaScript looks up any unqualified names within the set of statements to determine if the names are properties of the default object. If an unqualified name matches a property, then the property is used in the statement; otherwise, a local or global variable is used.
Which means that in the code sample, it is first checked if options is a property of sObj. If it is then options refers to sObj.options, otherwise it checks other scopes for a variable defined by the name options
The downside of using a with statement is that it is impossible to know from just glancing at the code what gets accessed. There are other better alternatives as shown in this article
It brings pain and suffering among you and others

Categories