JS: rename variables for refactor (using an AST, not text) - javascript

I often need to rename variables when refactoring code, which I currently do in a somewhat hacky way using regexs - I end up having to come with silly text workaround workarounds for the lack of actual structure, eg, rename 'req' to 'request' and avoid side effects with similar names like 'require'.
Thinking about this stuff: it's kind of like modifying the DOM with regexs: it just doesn't work.
I've learnt about ASTs and code structure modification tools like Esprima. Is there a tool to rename variables, Esprima based or otherwise?

1. grasp.js
It looks like http://graspjs.com/ does exactly this.
grasp selector --replace replacement file.js
For example, to rename 'el' to 'element':
grasp '#el' --replace 'element' index.js
Official grasp.replace docs.
2. vscode
Visual Studio Code also includes a real replacement tool. Just right click a token and choose rename symbol.

I know you've been asking for 'a tool'; but I think it's better to use just esprima itself and the various general purpose tools on top of esprima, and roll your own renamer. Because it's really really easy, and then you have more control. Here is a complete example in just 12 lines of code. It uses escodegen and estraverse, both on github, and, as far as I can see kind of 'the standard' to use in conjunction with esprima. While esprima essentially gives the parse function string -> abstract syntax tree, escodegen essentially gives the reverse of that, i.e. abstract syntax tree -> string. And estraverse 'walks the tree' with the traverse method, thus helping to analyze or modify it.
Here the code:
function rename(code, renamingObj){
var ast = esprima.parse(code);
function callback(node){
if (node.type==='Identifier') {
if (node.name in renamingObj){
node.name = renamingObj[node.name];
}
}
}
estraverse.traverse(ast, { enter: callback });
return escodegen.generate(ast);
}
Testcase:
function blah(x,y){
var difference = x + y;
var product = x - y;
var sum = x * y;
return 42;
}
var renamingObj = {
sum : 'product',
difference : 'sum',
product : 'difference'
};
run it:
rename(blah.toString(), renamingObj)
output:
function blah(x, y) {
var sum = x + y;
var difference = x - y;
var product = x * y;
return 42;
}
I would say, if you have something special to do, it's easier to modify above code than sifting through some tool documentation.

Our JavaScript Formatter/Obfuscator will do this reliably. It parses JavaScript, builds an AST, and either prints a pretty version, or an ugly (obfuscated) version. [The reason these are together is because pretty and ugly are opposite sides of the same coin!).
One of the things it does is scramble (whole) identifier names. By using the AST, it only renames "whole identifiers"; it won't confuse "req" with "require", or modify string or comment content by accident.
You can tell it to build a map of all identifier names, and then rename them all to themselves; change just one, and you get your rename effect. The identifier map looks like this:
x -> y
p -> q
...
directing that x gets renamed to y, p to q, etc. You want:
x -> x
p -> q
...
to change just p to q. Its pretty easy to produce the identity map
as your starting place.
I wouldn't say this is convenient, but it does work. It obviously doesn't
know anything about scopes. (someday!).
See my bio for details. Many SO moderators hate tool questions, and they especially seem to dislike it when I provide a tool answer that includes a link to the tool. So you'll have to track down the link yourself, sorry. (Complain on Meta if you think this is dumb).

Related

Javascript - Is there an easier way to read obfuscated, condensed code?

Is the code below an example of obfuscation? Is there a way to make code that has been obfuscated easier to interpret or follow the actions that lead through the script using chrome or firefox browsers? Are the original naming conventions somewhere behind the scenes? In other words, could I de-obfuscate the code short of downloading a couple hundred lines and then renaming everything based on what I think is happening?
main: function (a, b, c, d, e) {
var r,
o,
s = null != t ? t : {
},
l = i.helperMissing,
c = 'function',
d = e.escapeExpression;
That code is a result of minification and obfuscation which results in condensed code, and thus unreadable code. The entire point of minification is to reduce file size, so you the "real" function, attribute, and values aren't stored somewhere to be found. The idea of obfuscation is to make the code hard to decypher and "steal".
If you found this somewhere and the file ended in .min.js, you can always see if the same file exists in that location without the .min part in the filename.
For example
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js
Also, it would be near impossible for software to deobfuscate code, but you could read through it and try to understand its meaning. Here's a simple example
x=(a,b)=>a+b // obfuscated/minified code
function sum(number1, number2) { return number1 + number2 } // original code

Find out where this function has been called?

I want to be able to quickly go through all invocations of a function inside a file or outside. Currently i use search in all files method. But is there a way to see where this method was used.
Optional: Also i'd want to go back in other direction as well. Say there is a method call like this:
makeBread();
Now i want to see what the function do. so somehow jump to its declaration.
Find invocation
Trying to use text search to find invocations may easily betray you. Consider this:
function myFunction() {
console.log("Hello :)");
}
document.getElementById("page-title").addEventListener("click", myFunction);
I think you understand where this is going - if you want to get a list of invocations, best bet is to use console.trace at runtime:
function myFunction() {
console.trace();
console.log("Hello :)");
}
Find what the function does
The function can be overriden at runtime. Dynamic languages cannot be analysed like static ones (C++, Java). You wanna know what the function does? Print it in the console at runtime:
console.log(makeBread.toString());
Find declaration
Again, console.trace will tell you the line for every function it came through. You can also get the stack trace as array - but beware that this slows execution a lot, so don't do it in production.
Conclusion
As I said, you cannot inspect dynamic languages where anything can be anything using any IDE reliably. Most IDEs give good hints though, just conbine them with runtime debuging. Consider debuging running application more fun than looking ad the dead code.
More reading
If you want to make some reguler expressions, this is gonna be handy: http://www.bryanbraun.com/2014/11/27/every-possible-way-to-define-a-javascript-function
The console object: https://developer.mozilla.org/en-US/docs/Web/API/Console
Using stack trace: https://stackoverflow.com/a/635852/607407
Not natively, but with plugins, yes
A popular plugin that has this functionality is SublimeCodeIntel:
SublimeCodeIntel will also allow you to jump around symbol definitions even across files with just a click ..and back.
For Mac OS X:
Jump to definition = Control+Click
Jump to definition = Control+Command+Alt+Up
Go back = Control+Command+Alt+Left
Manual Code Intelligence = Control+Shift+space
For Linux:
Jump to definition = Super+Click
Jump to definition = Control+Super+Alt+Up
Go back = Control+Super+Alt+Left
Manual Code Intelligence = Control+Shift+space
For Windows:
Jump to definition = Alt+Click
Jump to definition = Control+Windows+Alt+Up
Go back = Control+Windows+Alt+Left
Manual Code Intelligence = Control+Shift+space

Javascript: What is a nice curry example? [duplicate]

I don’t think I’ve grokked currying yet. I understand what it does, and how to do it. I just can’t think of a situation I would use it.
Where are you using currying in JavaScript (or where are the main libraries using it)? DOM manipulation or general application development examples welcome.
One of the answers mentions animation. Functions like slideUp, fadeIn take an element as an arguments and are normally a curried function returning the high order function with the default “animation function” built-in. Why is that better than just applying the higher-up function with some defaults?
Are there any drawbacks to using it?
As requested here are some good resources on JavaScript currying:
http://www.dustindiaz.com/javascript-curry/
Crockford, Douglas (2008) JavaScript: The Good Parts
http://www.svendtofte.com/code/curried_javascript/
(Takes a detour into ML so skip the whole section from “A crash course in ML” and start again at “How to write curried JavaScript”)
http://web.archive.org/web/20111217011630/http://blog.morrisjohns.com:80/javascript_closures_for_dummies
How do JavaScript closures work?
http://ejohn.org/blog/partial-functions-in-javascript (Mr. Resig on the money as per usual)
http://benalman.com/news/2010/09/partial-application-in-javascript/
I’ll add more as they crop up in the comments.
So, according to the answers, currying and partial application in general are convenience techniques.
If you are frequently “refining” a high-level function by calling it with same configuration, you can curry (or use Resig’s partial) the higher-level function to create simple, concise helper methods.
Here's an interesting AND practical use of currying in JavaScript that uses closures:
function converter(toUnit, factor, offset, input) {
offset = offset || 0;
return [((offset + input) * factor).toFixed(2), toUnit].join(" ");
}
var milesToKm = converter.curry('km', 1.60936, undefined);
var poundsToKg = converter.curry('kg', 0.45460, undefined);
var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32);
milesToKm(10); // returns "16.09 km"
poundsToKg(2.5); // returns "1.14 kg"
farenheitToCelsius(98); // returns "36.67 degrees C"
This relies on a curry extension of Function, although as you can see it only uses apply (nothing too fancy):
Function.prototype.curry = function() {
if (arguments.length < 1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat([].slice.apply(null, arguments)));
}
}
#Hank Gay
In response to EmbiggensTheMind's comment:
I can't think of an instance where currying—by itself—is useful in JavaScript; it is a technique for converting function calls with multiple arguments into chains of function calls with a single argument for each call, but JavaScript supports multiple arguments in a single function call.
In JavaScript—and I assume most other actual languages (not lambda calculus)—it is commonly associated with partial application, though. John Resig explains it better, but the gist is that have some logic that will be applied to two or more arguments, and you only know the value(s) for some of those arguments.
You can use partial application/currying to fix those known values and return a function that only accepts the unknowns, to be invoked later when you actually have the values you wish to pass. This provides a nifty way to avoid repeating yourself when you would have been calling the same JavaScript built-ins over and over with all the same values but one. To steal John's example:
String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );
Agreeing with Hank Gay - It's extremely useful in certain true functional programming languages - because it's a necessary part. For example, in Haskell you simply cannot take multiple parameters to a function - you cannot do that in pure functional programming. You take one param at a time and build up your function. In JavaScript it's simply unnecessary, despite contrived examples like "converter". Here's that same converter code, without the need for currying:
var converter = function(ratio, symbol, input) {
return (input*ratio).toFixed(2) + " " + symbol;
}
var kilosToPoundsRatio = 2.2;
var litersToUKPintsRatio = 1.75;
var litersToUSPintsRatio = 1.98;
var milesToKilometersRatio = 1.62;
converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs
converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints
converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints
converter(milesToKilometersRatio, "km", 34); //55.08 km
I badly wish Douglas Crockford, in "JavaScript: The Good Parts", had given some mention of the history and actual use of currying rather than his offhanded remarks. For the longest time after reading that, I was boggled, until I was studying Functional programming and realized that's where it came from.
After some more thinking, I posit there is one valid use case for currying in JavaScript: if you are trying to write using pure functional programming techniques using JavaScript. Seems like a rare use case though.
I found functions that resemble python's functools.partial more useful in JavaScript:
function partial(fn) {
return partialWithScope.apply(this,
Array.prototype.concat.apply([fn, this],
Array.prototype.slice.call(arguments, 1)));
}
function partialWithScope(fn, scope) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
};
}
Why would you want to use it? A common situation where you want to use this is when you want to bind this in a function to a value:
var callback = partialWithScope(Object.function, obj);
Now when callback is called, this points to obj. This is useful in event situations or to save some space because it usually makes code shorter.
Currying is similar to partial with the difference that the function the currying returns just accepts one argument (as far as I understand that).
Consider filter function. And you want to write a callback for it.
let x = [1,2,3,4,5,6,7,11,12,14,15];
let results = x.filter(callback);
Assume want to output only even numbers, so:
let callback = x => x % 2 === 0;
Now imagine we want to implement our callback such that
depending on scenario it outputs even numbers which are above some threshold number (such
number should be configurable).
We can't easily make such threshold number a parameter to callback function, because filter invokes callback and by default passes it array elements and index.
How would you implement this?
This is a good use case for currying:
let x = [1,2,3,4,5,6,7,11,12,14,15];
let callback = (threshold) => (x) => (x % 2==0 && x > threshold);
let results1 = x.filter(callback(5)); // Even numbers higher than 5
let results2 = x.filter(callback(10)); // Even numbers higher than 10
console.log(results1,results2);
I know its old thread but I will have to show how this is being used in javascript libraries:
I will use lodash.js library to describe these concepts concretely.
Example:
var fn = function(a,b,c){
return a+b+c+(this.greet || ‘');
}
Partial Application:
var partialFnA = _.partial(fn, 1,3);
Currying:
var curriedFn = _.curry(fn);
Binding:
var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}
usage:
curriedFn(1)(3)(5); // gives 9
or
curriedFn(1,3)(5); // gives 9
or
curriedFn(1)(_,3)(2); //gives 9
partialFnA(5); //gives 9
boundFn(5); //gives 9!
difference:
after currying we get a new function with no parameters pre bound.
after partial application we get a function which is bound with some parameters prebound.
in binding we can bind a context which will be used to replace ‘this’, if not bound default of any function will be window scope.
Advise: There is no need to reinvent the wheel. Partial application/binding/currying are very much related. You can see the difference above. Use this meaning anywhere and people will recognise what you are doing without issues in understanding plus you will have to use less code.
It's no magic or anything... just a pleasant shorthand for anonymous functions.
partial(alert, "FOO!") is equivalent to function(){alert("FOO!");}
partial(Math.max, 0) corresponds to function(x){return Math.max(0, x);}
The calls to partial (MochiKit terminology. I think some other libraries give functions a .curry method which does the same thing) look slightly nicer and less noisy than the anonymous functions.
As for libraries using it, there's always Functional.
When is it useful in JS? Probably the same times it is useful in other modern languages, but the only time I can see myself using it is in conjunction with partial application.
I would say that, most probably, all the animation library in JS are using currying. Rather than having to pass for each call a set of impacted elements and a function, describing how the element should behave, to a higher order function that will ensure all the timing stuff, its generally easier for the customer to release, as public API some function like "slideUp", "fadeIn" that takes only elements as arguments, and that are just some curried function returning the high order function with the default "animation function" built-in.
Here's an example.
I'm instrumenting a bunch of fields with JQuery so I can see what users are up to. The code looks like this:
$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);
(For non-JQuery users, I'm saying that any time a couple of fields get or lose focus, I want the trackActivity() function to be called. I could also use an anonymous function, but I'd have to duplicate it 4 times, so I pulled it out and named it.)
Now it turns out that one of those fields needs to be handled differently. I'd like to be able to pass a parameter in on one of those calls to be passed along to our tracking infrastructure. With currying, I can.
JavaScript functions is called lamda in other functional language. It can be used to compose a new api (more powerful or complext function) to based on another developer's simple input. Curry is just one of the techniques. You can use it to create a simplified api to call a complex api. If you are the develper who use the simplified api (for example you use jQuery to do simple manipulation), you don't need to use curry. But if you want to create the simplified api, curry is your friend. You have to write a javascript framework (like jQuery, mootools) or library, then you can appreciate its power. I wrote a enhanced curry function, at http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html . You don't need to the curry method to do currying, it just help to do currying, but you can always do it manually by writing a function A(){} to return another function B(){}. To make it more interesting, use function B() to return another function C().
I agree that at times you would like to get the ball rolling by creating a pseudo-function that will always have the value of the first argument filled in. Fortunately, I came across a brand new JavaScript library called jPaq (http://jpaq.org/) which provides this functionality. The best thing about the library is the fact that you can download your own build which contains only the code that you will need.
Just wanted to add some resources for Functional.js:
Lecture/conference explaining some applications
http://www.youtube.com/watch?v=HAcN3JyQoyY
Updated Functional.js library:
https://github.com/loop-recur/FunctionalJS
Some nice helpers (sorry new here, no reputation :p):
/loop-recur/PreludeJS
I've been using this library a lot recently to reduce the repetition in an js IRC clients helper library. It's great stuff - really helps clean up and simplify code.
In addition, if performance becomes an issue (but this lib is pretty light), it's easy to just rewrite using a native function.
You can use native bind for quick, one line solution
function clampAngle(min, max, angle) {
var result, delta;
delta = max - min;
result = (angle - min) % delta;
if (result < 0) {
result += delta;
}
return min + result;
};
var clamp0To360 = clampAngle.bind(null, 0, 360);
console.log(clamp0To360(405)) // 45
Another stab at it, from working with promises.
(Disclaimer: JS noob, coming from the Python world. Even there, currying is not used all that much, but it can come in handy on occasion. So I cribbed the currying function - see links)
First, I am starting with an ajax call. I have some specific processing to do on success, but on failure, I just want to give the user the feedback that calling something resulted in some error. In my actual code, I display the error feedback in a bootstrap panel, but am just using logging here.
I've modified my live url to make this fail.
function ajax_batch(e){
var url = $(e.target).data("url");
//induce error
url = "x" + url;
var promise_details = $.ajax(
url,
{
headers: { Accept : "application/json" },
// accepts : "application/json",
beforeSend: function (request) {
if (!this.crossDomain) {
request.setRequestHeader("X-CSRFToken", csrf_token);
}
},
dataType : "json",
type : "POST"}
);
promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}
Now, here in order to tell the user that a batch failed, I need to write that info in the error handler, because all it is getting is a response from the server.
I still only have the info available at coding time - in my case I have a number of possible batches, but I don't know which one has failed w.o. parsing the server response about the failed url.
function fail_status_specific_to_batch(d){
console.log("bad batch run, dude");
console.log("response.status:" + d.status);
}
Let's do it. Console output is:
console:
bad batch run, dude
utility.js (line 109)
response.status:404
Now, let's change things a bit and use a reusable generic failure handler, but also one that is curried at runtime with both the known-at-code-time calling context and the run-time info available from event.
... rest is as before...
var target = $(e.target).text();
var context = {"user_msg": "bad batch run, dude. you were calling :" + target};
var contexted_fail_notification = curry(generic_fail, context);
promise_details.then(notify_batch_success, contexted_fail_notification);
}
function generic_fail(context, d){
console.log(context);
console.log("response.status:" + d.status);
}
function curry(fn) {
var slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function () {
var new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
};
}
console:
Object { user_msg="bad batch run, dude. you were calling :Run ACL now"}
utility.js (line 117)
response.status:404
utility.js (line 118)
More generally, given how widespread callback usage is in JS, currying seems like a quite useful tool to have.
https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/
http://www.drdobbs.com/open-source/currying-and-partial-functions-in-javasc/231001821?pgno=2
I asked a similar question at https://softwareengineering.stackexchange.com/questions/384529/a-real-life-example-of-using-curry-function
But only after I use ramda do I finally appreciate the usefulness of curry. So I will argue that if we need to chain functions together to process some input data one step a time, e.g. the promise chain example in the article Favoring Curry, using curry by "function first,data last", the code does look clean!
Here you have a practical example of were currying is being used at the moment.
https://www.joshwcomeau.com/react/demystifying-styled-components/
Basically he is creating a poor man styled components and uses currying to "preload" the name of the tag when creating a new style for it.

How do languages handle side effects of compound operators?

Assume such situation:
int a = (--t)*(t-2);
int b = (t/=a)+t;
In C and C++ this is undefined behaviour, as described here: Undefined behavior and sequence points
However, how does this situation look in:
JavaScript,
Java,
PHP...
C#
well, any other language which has compound operators?
I'm bugfixing a Javascript -> C++ port right now in which this got unnoticed in many places. I'd like to know how other languages generally handle this... Leaving the order undefined is somehow specific to C and C++, isn't it?
According to the ECMA Script specification, which I believe javascript is supposed to conform to, in multiplication and addition statements, it evaluates the left hand side before evaluating the right hand side. (see 11.5 and 11.6). I think this means that the code should be equivalent to
t = t - 1;
int a = t * (t - 2);
t = t / a;
int b = t + t;
However, you should not always trust the specification to be the same as the implementation!
Your best bet in confusing cases like this is to experiment with various inputs to the ambiguous lines of code in the original operating environment, and try to determine what it is doing. Make sure to test cases that can confirm a hypothesis, and also test cases that can falsify it.
Edit: Apparently most JavaScript implements the 3rd edition of ECMAScript, so I changed the link to that specification instead.
Practically speaking, if you have to ask or look up the rules for an expression, you shouldn't be using that expression in your code. Someone else will come back two years from now and get it wrong, then rewrite it and break the code.
If this was intended as a strictly theoretical question I unfortunately can't offer details regarding those other languages.
For javascript the following article should help.
This article clearly states whether a particular combination of
a OP b OP c goes from left-to-right and in which order.
I'm don't know about the other languages.
However, how does this situation look in: JS, Java, PHP, C#...
To be perfectly candid, int a = (--t)*(t-2); int b = (t/=a)+t; looks like crap.
It's nice to have fancy code that can be all pretty and elitist, but there's absolutely no need for it. The solution for every language when confronted with code like this is to add a couple more semi-colons (unless you're dealing with python):
--t;
int a = t * (t-2);
t /= a;
int b = t + t;
-or-
int b = t * 2;
-or-
int b = t << 1;
//whichever method you prefer
If a different order of operations is desired, the adjust the lines accordingly. If you're trying to fix old buggy code, fix the code, don't just re-implement someone else's spaghetti.
Edit to add:
I realized I never specifically answered the original question:
How do languages handle side effects of compound operators?
Poorly.

Good resources for extreme minified JavaScript (js1k-style)

As I'm sure most of the JavaScripters out there are aware, there's a new, Christmas-themed js1k. I'm planning on entering this time, but I have no experience producing such minified code. Does anyone know any good resources for this kind of thing?
Google Closure Compiler is a good javascript minifier.
There is a good online tool for quick use, or you can download the tool and run it as part of a web site build process.
Edit: Added a non-exhaustive list of tricks that you can use to minify JavaScript extremely, before using a minifier:
Shorten long variable names
Use shortened references to built in variables like d=document;w=window.
Set Interval
The setInterval function can take either a function or a string. Pass in a string to reduce the number of characters used: setInterval('a--;b++',10). Note that passing in a string forces an eval invokation so it will be slower than passing in a function.
Reduce Mathematical Calculations
Example a=b+b+b can be reduced to a=3*b.
Use Scientific Notation
10000 can be expressed in scientific notation as 1E4 saving 2 bytes.
Drop leading Zeroes
0.2 = .2 saves a byte
Ternery Operator
if (a > b) {
result = x;
}
else {
result = y;
}
can be expressed as result=a>b?x:y
Drop Braces
Braces are only required for blocks of more than one statement.
Operator Precedence
Rely on operator precedence rather than adding unneeded brackets which aid code readability.
Shorten Variable Assignment
Rather than function x(){a=1,b=2;...}() pass values into the function, function x(a,b){...}(1,2)
Think outside the box
Don't automatically reach for standard ways of doing things. Rather than using d.getElementById('p') to get a reference to a DOM element, could you use b.children[4] where d=document;b=body.
Original source for above list of tricks:
http://thingsinjars.com/post/293/the-quest-for-extreme-javascript-minification/
Spolto is right.
Any code minifier won't do the trick alone. You need to first optimize your code and then make some dirty manual tweaks.
In addition to Spolto's list of tricks I want to encourage the use of logical operators instead of the classical if else syntax. ex:
The following code
if(condition){
exp1;
}else{
exp2;
}
is somewhat equivalent to
condition&&exp1||exp2;
Another thing to consider might be multiple variable declaration :
var a = 1;var b = 2;var c = 1;
can be rewritten as :
var a=c=1,b=2;
Spolto is also right about the braces. You should drop them. But in addition, you should know that they can be dropped even for blocks of more expressions by writing the expressions delimited by a comma(with a leading ; of course) :
if(condition){
exp1;
exp2;
exp3;
}else{
exp4;
exp5;
}
Can be rewritten as :
if(condition)exp1,exp2,exp3;
else exp4,exp5;
Although it's not much (it saves you only 1 character/block for those who are counting), it might come in handy. (By the way, the latest Google Closure Compiler does this trick too).
Another trick worth mentioning is the controversial with functionality.
If you care more about the size, then you should use this because it might reduce code size.
For example, let's consider this object method:
object.method=function(){
this.a=this.b;
this.c++;
this.d(this.e);
}
This can be rewritten as :
object.method=function(){
with(this){
a=b;
c++;
d(e);
}
}
which is in most cases signifficantly smaller.
Something that most code packers & minifiers do not do is replacing large repeating tokens in the code with smaller ones. This is a nasty hack that also requires the use of eval, but since we're in it for the space, I don't think that should be a problem. Let's say you have this code :
a=function(){/*code here*/};
b=function(){/*code here*/};
c=function(){/*code here*/};
/*...*/
z=function(){/*code here*/};
This code has many "function" keywords repeating. What if you could replace them with a single(unused) character and then evaluate the code?
Here's how I would do it :
eval('a=F(){/*codehere*/};b=F(){/*codehere*/};c=F(){/*codehere*/};/*...*/z=F(){/*codehere*/};'.replace(/function/g,'F'));
Of course the replaced token(s) can be anything since our code is reduced to an evaluated string (ex: we could've replaced =function(){ with F, thus saving even more characters).
Note that this technique must be used with caution, because you can easily screw up your code with multiple text replacements; moreover, you should use it only in cases where it helps (ex: if you only have 4 function tokens, replacing them with a smaller token and then evaluating the code might actually increase the code length :
var a = "eval(''.replace(/function/g,'F'))".length,
b = ('function'.length-'F'.length)*4;
alert("you should" + (a<b?"":" NOT") + " use this technique!");
In the following link you'll find surprisingly good tricks to minify js code for this competition:
http://www.claudiocc.com/javascript-golfing/
One example: (extracted from section Short-circuit operators):
if (p) p=q; // before
p=p&&q; // after
if (!p) p=q; // before
p=p||q; // after
Or the more essoteric Canvas context hash trick:
// before
a.beginPath
a.fillRect
a.lineTo
a.stroke
a.transform
a.arc
// after
for(Z in a)a[Z[0]+(Z[6]||Z[2])]=a[Z];
a.ba
a.fc
a.ln
a.sr
a.to
a.ac
And here is another resource link with amazingly good tricks: https://github.com/jed/140bytes/wiki/Byte-saving-techniques
First off all, just throwing your code into a minifier won't help you that much. You need to have the extreme small file size in mind when you write the code. So in part, you need to learn all the tricks yourself.
Also, when it comes to minifiers, UglifyJS is the new shooting star here, its output is smaller than GCC's and it's way faster too. And since it's written in pure JavaScript it should be trivial for you to find out what all the tricks are that it applies.
But in the end it all comes down to whether you can find an intelligent, small solution for something that's awsome.
Also:
Dean Edwards Packer
http://dean.edwards.name/packer/
Uglify JS
http://marijnhaverbeke.nl/uglifyjs
A friend wrote jscrush packer for js1k.
Keep in mind to keep as much code self-similar as possible.
My workflow for extreme packing is: closure (pretty print) -> hand optimizations, function similarity, other code similarity -> closure (whitespace only) -> jscrush.
This packs away about 25% of the data.
There's also packify, but I haven't tested that myself.
This is the only online version of #cowboy's packer script:
http://iwantaneff.in/packer/
Very handy for packing / minifying JS

Categories

Resources