These are some of my syntactic sugar ideas for JavaScript.
#define add(a,b) a+b
console.log(add(4,7)); //Will output 11.
#define array [2,3]
console.log(array.pop()+array[1]); //Will output 6.
Useful for code golfing.
But its biggest purpose is for debugging like in this example:
#define DEBUG
for(var i=0;i<iterations;i++){
#ifdef DEBUG
debugFunction(param1,param2,param3);
#else
normalFunction(param1,param2,param3);
#endif
}
Instead of:
const DEBUG=true;
for(var i=0;i<iterations;i++){
if(DEBUG){
debugFunction(param1,param2,param3);
}else{
normalFunction(param1,param2,param3);
}
}
So you could keep parts of your code without ruining your performance with if-statements, comments do exist of course but I get tired of uncommenting and commenting especially if they're spread separately in different areas.
Looping without using any variables.
loop{ //You could do `for(;;){`.
//Infinite loop.
}
loop(7){
//Loop 7 times.
}
Instead of:
var object={
a:"Hello",
get b(){return this.a;},
set b(value){this.a=value;}
};
Do this:
var object={
["a","b"]:"Hello"
};
object.a="Test";
console.log(object.a); //Will output "Test".
console.log(object.b); //Will output "Test".
This can sometimes be useful for dictionaries (e.g. the array can consist of synonyms and the value can be a definition).
This can also be useful for GLSL-like vectors (e.g. ({[..."xrs0"]:0,[..."ygt1"]:0,[..."zbp2"]:0,[..."waq3"]:0})
).
Instead of:
var array=[0,1];
console.log(array.reduce((t,e)=>t[e],[[6,3],6])); //Will output 3.
Do this:
var array=[0,1];
console.log([[6,3],6]array); //Same as `[[6,3],6][0][1]` and will output 3.
Where self
's value is the variable itself:
var incrediblyLongVariableName="llo";
incrediblyLongVariableName="He"+self+", world!";
console.log(incrediblyLongVariableName); //Will output "Hello, world!".
var object={a:3,b:7,c:self.a+self.b};
//`object.c=object.a+object.b;` would've been here without `self`.
console.log(object.c); //Will output 10.
Can be used for negating booleans (e.g. boolean=!self;
) and recursive anonymous functions such as:
console.log((x=>x>1?Math.log(x)**self(x-1):x)(6));
It can also be used for polyfills:
globalObject.prototype.method=self|function method(...arguments){
//...
};
Afterthought: What about this? itself
which is the value of the current local object (scope) it's being inside of?
From this:
var temp0={
y:5,
get x(){return this.y;},
set x(v){this.y=v;}
};
temp0.z=[0,undefined];
temp0.z[1]=temp0.z;
var temp1=n=>n<2?n:temp1(n-1)+temp1(n-2);
var result=(o=>temp1(o.x))(temp0);
To this:
var result=(o=>(n=>n<2?n:itself(n-1)+itself(n-2))(o.x))({x:itself.y,y:5,z:[0,itself]});
Another afterthought: Why can't we use temporary "variables", like this:
x:longVariableName=(6/x)+x;
Which becomes:
longVariableName=(6/longVariableName)+longVariableName;
Similar to this feature:
#define x longVariableName
x=(6/x)+x;
Instead of:
(
var x=longVariableName;
longVariableName=(6/x)+x;
)(); //Wrapped in an anonymous function so that `x` isn't defined.
Instead of:
var a="foo";
if(a=="foo"){
console.log('Got "foo".');
}else if((()=>{a+="bar";return a=="bazbar";})()){
console.log('Got "baz".');
}
while((()=>{a+="bar";return a.length<20;})()){
console.log(a);
}
Do this:
var a="foo";
if(a=="foo"){
console.log('Got "foo".');
}else if(a+="bar";a=="bazbar"){
console.log('Got "baz".');
}
while(a+="bar";a.length<20){
console.log(a);
}
Actually, with commas you can achieve the same effect:
var a="foo";
if(a=="foo"){
console.log('Got "foo".');
}else if(a+="bar",a=="bazbar"){
console.log('Got "baz".');
}
while(a+="bar",a.length<20){
console.log(a);
}
Instead of:
(async()=>{
console.log("Sleeping for two seconds.");
await new Promise(resolve=>setTimeout(resolve,2000));
console.log("Done.");
})();
Do this:
console.log("Sleeping for two seconds.");
sleep(2000);
console.log("Done.");
Instead of:
var string="";
function A(){string+="Hello ";B();};
function B(){string+="there! ";C();};
function C(){string+="How are you?";};
A();
console.log(string); //Will output "Hello there! How are you?".
Do this:
var string="";
goto A;
B:string+="there! ";goto C;
A:string+="Hello ";goto B;
C:string+="How are you?";
console.log(string); //Will output "Hello there! How are you?".
var x=4;
link y,x;
y++;
console.log(x); //Will output 5.
Which in C would be like:
int x=4;
int*y=&x;
(*y)++;
printf("%d",x);
Can be used for variables with long names but I'd recommend this instead in some cases.
class vec2{
constructor(x,y){
this.x=x;
this.y=y;
}
__plus(left){
return{x:left.x+this.x,y:left.y+this.y};
}
__minus(left){
return{x:left.x-this.x,y:left.y-this.y};
}
}
console.log(new vec2(6,4)+new vec2(3,9)); //Will output {x:9,y:13}.
or
overload # (left:Number,right:Number){
return left+right;
}
console.log(5#8); //Will output 13.
Instead of:
console.log("foo bar baz".replace(/a/g,"e").replace(/o/g,"u")); //Output will be "fuu ber bez".
Do this:
console.log("foo bar baz".replace([/a/g,/o/g],["e","u"])); //Output will be "fuu ber bez".
Or even this, so you can easily comprehend the correlations:
console.log("foo bar baz".replace([[/a/g,"e"],[/o/g,"u"]])); //Output will be "fuu ber bez".
Such as named capturing groups, if-then-else conditionals (e.g. (?(?=condition)then|else)
), lookbehinds (e.g. (?=condition)match
) and etc..
I've seen Wren doing this, useful for debugging or describing a metalanguage. Example:
/*
breaksStuff(x);
/*
Some text here.
Another line.
*/
ignored();
*/
doThis();
A getTimeouts()
function to return all timeoutID
s and more information about their elapsed time, functions and additional parameters, don't forget about getIntervals()
for intervalID
s. Also allow the delay to be greater than 2147483647 milliseconds.
Where this:
var x=2;
switch(x){
case 2:
case 5:
console.log("First.");
break 5;
console.log("Second.");
}
Becomes this:
var x=2;
switch(x){
case 2:
case 5:
console.log("First.");
if(x===5){break;}
console.log("Second.");
}
And this:
var x=0;
switch(x){
case 6:
console.log("Done!");
break;
default:
console.log(x);
x++;
continue;
}
Becomes this:
var x=0;
while(true){
if(x===6){
console.log("Done!");
break;
}else{
console.log(x);
x++;
}
}