Tipps zum Golfen in JavaScript

133

Welche allgemeinen Tipps haben Sie zum Golfen in JavaScript? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas spezifisch für JavaScript sind (z. B. "Kommentare entfernen" ist keine Antwort).

Hinweis: Siehe auch Tipps zum Golfen in ECMAScript 6 und höher

mellamokb
quelle
Ich habe mich gefragt, ob es erlaubt ist, Variablen in global (saves var) zu schreiben. Und sollte JavaScript Golf Code eine Funktion sein oder etwas direkt ausgeben? Ich denke ehrlich, das kann viel bewirken.
Pimvdb
1
@primvdb: Es ist erlaubt, aber Sie müssen vorsichtig sein, da es zu Nebenwirkungen kommen kann, wenn eine Funktion mehrmals aufgerufen wird und globale Variablen manipuliert werden oder wenn es sich um eine rekursive Funktion handelt.
Mellamokb

Antworten:

108

Lust auf Loops

Sie können die standard for-Schleife auf nicht standardmäßige Weise verwenden

for ( a; b; c )

ist im Wesentlichen gleichbedeutend mit:

a;
while ( b )
{
  ...
  c;
}

Ein guter Trick ist es, den Code mit einer whileSchleife zu schreiben und ihn dann in die a,b,cTeile einer forSchleife zu teilen .

Ein paar Beispiele, die ich geschrieben habe :

for(x=y=n;!z;x--,y++)z=i(x)?x:i(y)?y:0
for(a=b=1;b<n;c=a+b,a=b,b=c);

Verkette deine Setter

Wenn Sie mehrere Werte initialisieren oder zurücksetzen, verketten Sie den Wert mit allen Variablen, die ihn benötigen:

a=b=1;

Implizites Casting

Überprüfen Sie Ihre Typen nicht, sondern verwenden Sie sie so, wie sie sind. parseInt()kostet 10Zeichen. Wenn Sie aus einer Zeichenfolge streichen müssen, müssen Sie kreativ sein:

a='30';
b='10';
c = a + b; //failure
c = parseInt(a) + parseInt(b) //too long

c = -(-a-b); //try these
c = ~~a+~~b;
c = +a+ +b;
c = a- -b;

Vermeiden Sie Semikolons

JavaScript verfügt über eine automatische Semikoloneinfügung. Verwenden Sie es oft und gut.

Einzeiler

Sparen Sie an den Klammern, indem Sie so viel wie möglich in einzelne Zeilen oder Parameter schieben:

a( realParam1, realParam2, fizz='buzz' )

Increment / Decrement-Operatoren

a = a - 1;
foo(a);

und

foo(a);
a = a - 1;

kann leicht umgeschrieben werden als

foo(--a);

und

foo(a--);

beziehungsweise.

Verwenden Sie thisoder selfanstelle von windowim globalen Kontext

Selbsterklärende 2-Zeichen-Ersparnis.

Verwenden Sie die Klammernotation für den wiederholten Zugriff auf Eigenschaften

Dies ist definitiv ein Spagat zwischen der Länge des Eigenschaftsnamens und der Anzahl der Zugriffe. Anstatt a.longFunctionName()zweimal mit Punktnotation aufzurufen , ist es kürzer, den Namen zu speichern und die Funktion in Klammern aufzurufen:

a.longFunctionName(b)
a.longFunctionName(c)
//42

-vs-

a[f='longFunctionName'](b)
a[f](c)
//34

Dies ist besonders effektiv bei Funktionen, auf document.getElementByIddie reduziert werden kann d[e].

Hinweis:

Bei Verwendung der Klammernotation sind die Kosten 6 + name.lengthbeim ersten Mal Zeichen. Jeder weitere Zugriff kostet 3Zeichen.

Bei der Punktnotation kosten alle Zugriffe name.length + 1(+1 für die .) Zeichen.

Verwenden Sie diese Methode, wenn 6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1).

len = Länge des Eigenschaftsnamens
i = Mindestzugriffe, um die Vorteile zu nutzen

len | i 
========
1   |  
2   |  
3   | 7 
4   | 4 
5   | 3 
6   | 3 
7   | 3 
8+  | 2 

Die Anzahl der Zugriffe kann auch mehrere Objekte umfassen. Wenn Sie .lengthin verschiedenen Arrays mindestens viermal zugreifen , können Sie dieselbe Variable verwenden, die die Zeichenfolge enthält 'length'.

zzzzBov
quelle
5
c = ~~a-~~bsollte sein c = ~~a+~~b. Sie können auch implizit in eine Ganzzahl umwandeln |0, indem Sie beispielsweise Folgendes verwenden Math.random()*6|0.
Mellamokb
7
Es ist billiger, eine Zeichenfolge mit dem Operator unary plus zu einer Zahl zu zwingen. Wenn aund bZeichenfolgen sind, können Sie diese +a+bin Zahlen konvertieren und hinzufügen.
Peter Olson
8
Ich schwöre, ich werde d- -beines Tages in meinem Code verwenden ...
John Dvorak
4
+ a + b funktioniert nicht (zumindest bei mir ...) // a = "1", b = "1", + a + b // ergibt "11"
imma
2
Für „Use Array-Zugang für Repeat - Funktion aufruft“ , wenn Sie die Funktion mehr als doppelt verwenden auf das gleiche Objekt , was ist ein bisschen kürzer wird , um die Funktion zu einem neuen Mitglied zuweisen wiea.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Martin Ender
131

Teilen mit Zahlen, um die Anführungszeichen zu speichern:

"alpha,bravo,charlie".split(",") // before
"alpha0bravo0charlie".split(0)   // after
ajax333221
quelle
2
Es funktioniert und ich habe es für mehrere Ziffern verwendet.
Isiah Meadows
12
Lol das ist eigentlich ziemlich kreativ
NiCk Newman
9
in ES6 spielt das keine Rolle mehr, du kannst es einfach tun.split`...`
David Archibald
"alpha,bravo,charlie".split`,`
Kamil Kiełczewski
56

Verwenden Sie den Komma-Operator, um geschweifte Klammern zu vermeiden ( gilt auch für C ):

if(i<10)m+=5,n-=3;

Anstatt von

if(i<10){m+=5;n-=3}

Das ist ein Zeichen länger.

mellamokb
quelle
2
Ist das Semikolon am Ende der ersten Stichprobe erforderlich?
WJL
4
@wjlafrance: Es wäre nur nicht erforderlich, wenn es am Ende des Einzeilers ist.
Mellamokb
48

Kürzere Zufallszahlengenerierung

Wenn Sie einen zufälligen Booleschen Wert ( 0oder 1) benötigen :

new Date&1 // equivalent to Math.random()<0.5

Wenn Sie eine zufällige Ganzzahl benötigen 0 <= n < 1337:

new Date%1337 // equivalent to Math.floor(Math.random()*1337))

Dies funktioniert, weil a Dateintern in JavaScript als die Anzahl der Millisekunden seit einer Epoche gespeichert new Dateist. 123somebignumber456Wenn Sie also versuchen, eine Ganzzahlberechnung durchzuführen, wird dies erzwungen.

Natürlich sind diese "zufälligen" Zahlen nicht so zufällig, besonders wenn Sie sie mehrere Male hintereinander aufrufen. Denken Sie also daran.

Türknauf
quelle
1
Ich habe mich beim Lesen an diese Antwort erinnert. Mehr Lügenprogrammierer glauben an die Zeit : „21. Wenn Sie zwei Datumsobjekte direkt nebeneinander erstellen, werden sie zur gleichen Zeit dargestellt. (ein fantastischer Heisenbug-Generator) “ .
Sebastian Simon
39

Sie können die Objektliteralform von get / set verwenden, um die Verwendung des Schlüsselworts zu vermeiden function.

var obj = {
  get f(){
    console.log("just accessing this variable runs this code");
    return "this is actually a function";
  },
  set f(v){
    console.log("you can do whatever you want in here, passed: " + v);
  }
};

1 && obj.f; // runs obj.[[get f]]
obj.f = Infinity; // runs obj.[[set f]](Infinity)

quelle
Der Getter / Setter-Teil war wirklich hilfreich. thx
gion_13
1
Noch besser ist eine Objektmethode, wenn Sie sie nur <= 2 Mal verwenden. Auf der anderen Seite können Pfeilfunktionen Zeichen viel besser reduzieren, da sie fast denselben Zweck erfüllen und Klassen im Golfcode selten nützlich sind.
Isiah Meadows
wenn unterstützung wichtig ist pfeilfunktionen werden in fx nicht unterstützt. ie11
Jim Wolff
35

Dieser ist weniger bekannt und wird seltener verwendet, kann aber beeindruckend sein, wenn er in der richtigen Situation verwendet wird. Betrachten Sie eine Funktion, die keine Argumente akzeptiert und beim Aufruf immer eine andere Zahl zurückgibt, und die zurückgegebene Zahl wird in einer Berechnung verwendet:

var a = [ 
    Math.random()*12|0,
    Math.random()*11|0,
    Math.random()*10|0,
    /* etc... */ 
];

Normalerweise können Sie diese Funktion mit einem einzigen Variablennamen abkürzen:

var r=Math.random,a=[r()*12|0,r()*11|0,r()*10|0,r()*9|0,r()*8|0,r()*7|0,r()*6|0,r()*5|0];

Ein besserer Weg, die Länge zu reduzieren, ist der Missbrauch valueOf, wodurch Sie 2 Zeichen pro Aufruf sparen. Nützlich, wenn Sie die Funktion mehr als fünfmal aufrufen:

var r={valueOf:Math.random},a=[r*12|0,r*11|0,r*10|0,r*9|0r*8|0,r*7|0,r*6|0,r*5|0];
Andy E
quelle
8
Oder Sie könnten es wie folgt machen: let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)oder let a=Array(7).map((_,i)=>i*Math.random()|0+5)36 bzw. 42 Bytes gespeichert.
Isiah Meadows
Kann man es ersetzen r()oder kürzer machen?
NiCk Newman
3
r={valueOf:Math.random}Das ist einfach genial: D
ETHproductions
1
@Isiah, na ja, das kannst du jetzt machen :-D
Andy E
32

Kurzschlussbetreiber ausnutzen

Anstatt lange ifAnweisungen oder ternäre Operatoren zu verwenden, können Sie Ihren Code verwenden &&und ||verkürzen. Zum Beispiel:

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : null;

kann werden

var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);

return match && decodeURIComponent(match[1].replace(/\+/g, ' '));

Der ||Operator wird häufig auf folgende Weise zum Festlegen von Standardeinstellungen verwendet:

evt = evt || window.event;

Dies ist das gleiche wie beim Schreiben

if (!evt)
    evt = window.event;

Erstellen sich wiederholender Zeichenfolgen mit Array

Wenn Sie eine lange Zeichenfolge eines bestimmten Zeichens initialisieren möchten, können Sie dazu ein Array mit einer Länge von n + 1 erstellen , wobei n die Häufigkeit ist, mit der Sie das Zeichen wiederholen möchten:

// Create a string with 30 spaces
str = "                              ";

// or
str = Array(31).join(" ");

Je größer die Saite, desto größer die Ersparnis.

Zahlen analysieren

Verwenden Sie +und ~-Operatoren anstelle von parseFloat()oder, parseInt()wenn Sie einen Zeichenfolgentyp, der nur eine Zahl ist, zu einem Zahlentyp zusammenfassen:

var num = "12.6";
parseFloat(num) === +num;  // + is 10 characters shorter than parseFloat()

var num2 = "12"
parseInt(num2) === +num2;   // + is 8 characters shorter than parseInt()

var num3 = "12.6"
parseInt(num3) === ~~num3;  // ~~ is 7 characters shorter than parseInt()

var num4 = "12.6"
parseInt(num4) === num4|0;  // |0 is 7 characters shorter than parseInt()

Seien Sie jedoch vorsichtig, andere Typen können mit diesen Operatoren verschmolzen werden (dies truewürde beispielsweise zu 1einer leeren Zeichenfolge werden ), oder eine Zeichenfolge, die nur Leerzeichen enthält , würde zu einer Zeichenfolge 0. Dies kann jedoch unter bestimmten Umständen nützlich sein.

Andy E
quelle
6
+1 für das Erstellen sich wiederholender Zeichenfolgen mit Array - daran habe ich nicht gedacht.
Mellamokb
4
Um sich wiederholende Zeichenfolgen zu erstellen, können Sie in ES6str.repeat(count)
Oriol
26

Schleichen Sie die Variableninitialisierung in den prompt () - Aufruf ein, um Benutzereingaben zu erhalten

n=prompt(i=5);     // sets i=5 at the same time as getting user input

anstatt zu verwenden

n=prompt();i=5;

Als Nebeneffekt wird der Eingabewert im Eingabeaufforderungsfenster angezeigt, während 1 Zeichen gespeichert wird.

mellamokb
quelle
12
Dies kann auch auf jede Funktion angewendet werden, die keine Argumente akzeptiert.
Casey Chu
3
Auch wenn die Funktion Argumente akzeptiert, kann dies nützlich sein, beispielsweise [1,2,3].join('',i=5)wenn ein Paar geschweifte Klammern gespeichert werden.
DocMax
3
@ DocMax: Sie könnten Komma-Operator dafür verwenden - i=5,[1,2,3].join().
Konrad Borowski
@GlitchMr: Ich könnte, aber es werden keine Zeichen gespeichert. Ich bin damit einverstanden, dass dies die meiste Zeit sauberer sein wird. Ich denke, es kann immer noch Fälle geben, in denen meine Bestellung einen Buchstaben erspart, obwohl ich momentan keinen finden kann (und ich kann mich gut irren).
DocMax
@DocMax Nur wenn Sie ASI nutzen.
Isiah Meadows
24

Für Schleifen verschachtelt kombinieren:

// before:
for(i=5;i--;)for(j=5;j--;)dosomething(i,j)

// after:
for(i=25;i--;)dosomething(0|i/5,i%5)

Beispiel mit unterschiedlichen Werten für i/ j:

// before:
for(i=4;i--;)for(j=7;j--;)dosomething(i,j)

// after:
for(i=28;i--;)dosomething(0|i/7,i%7)
Kae Verens
quelle
(Ich habe einen) kleinen Tippfehler bearbeitet, aber sehr klug! Beachten Sie, dass dies nur bei verschachtelten Schleifen gleicher Länge funktioniert (es sei denn, ich liege falsch).
Camilo Martin
1
@CamiloMartin Nein, die Loops müssen nicht gleich lang sein. Die resultierende Anzahl von Iterationen ist i*jund die Divisions- / Moduloperatoren rufen die einzelnen Werte von iund ab j.
quietmint
@ user113215 Du hast recht, super! :) Ich habe die Antwort so bearbeitet, dass sie ein Beispiel enthält.
Camilo Martin
23

Unicode-Verknüpfungen

Wenn Sie bei einer großen Golfherausforderung eine verdammt gute eingebaute Immobilie nutzen, können Sie jede Immobilie einem Ein-Zeichen-Äquivalent zuordnen:

[Math,Number,S=String,Array].map(b=>
    Object.getOwnPropertyNames(b).map((p,i)=>
        b.prototype[S.fromCharCode(i+248)]=b[p]
    )
)

Nachdem Sie den obigen Code ausgeführt haben, können Sie ihn folgendermaßen verwenden:
"foo".Č(/.*/,'bar') // replaces foo with bar

Dies kostet 118 Byte und ist in bestimmten Situationen möglicherweise nicht sinnvoll

Es kann browserabhängig sein und ich bin nicht sicher, ob es kürzer ist als with(Array){join(foo),...}Variablen oder sie als verwendete Eigenschaften definiert, with(Array){j=join,m=map...}aber es ist trotzdem erwähnenswert.

    Math        Number              String              Array

ø   toSource    prototype           prototype           prototype
ù   abs         NaN                 quote               join
ú   acos        POSITIVE_INFINITY   substring           reverse
û   asin        NEGATIVE_INFINITY   toLowerCase         sort
ü   atan        MAX_VALUE           toUpperCase         push
ý   atan2       MIN_VALUE           charAt              pop
þ   ceil        MAX_SAFE_INTEGER    charCodeAt          shift
ÿ   clz32       MIN_SAFE_INTEGER    contains            unshift
Ā   cos         EPSILON             indexOf             splice
ā   exp         isFinite            lastIndexOf         concat
Ă   floor       isInteger           startsWith          slice
ă   imul        isNaN               endsWith            filter
Ą   fround      toInteger           trim                isArray
ą   log         parseFloat          trimLeft            lastIndexOf
Ć   max         parseInt            trimRight           indexOf
ć   min         length              toLocaleLowerCase   forEach
Ĉ   pow         name                toLocaleUpperCase   map
ĉ   random      arguments           normalize           every
Ċ   round       caller              match               some
ċ   sin                             search              reduce
Č   sqrt                            replace             reduceRight
č   tan                             split   
Ď   log10                           substr  
ď   log2                            concat  
Đ   log1p                           slice   
đ   expm1                           fromCharCode    
Ē   cosh                            fromCodePoint   
ē   sinh                            localeCompare   
Ĕ   tanh                            length  
ĕ   acosh                           name    
Ė   asinh                           arguments   
ė   atanh                           caller  
Ę   hypot           
ę   trunc           
Ě   sign            
ě   cbrt            
Ĝ   E           
ĝ   LOG2E           
Ğ   LOG10E          
ğ   LN2         
Ġ   LN10            
ġ   PI          
Ģ   SQRT2           
ģ   SQRT1_2         
bebe
quelle
Ich verwende Google Chrome, und diese geben alle undefined.
SuperJedi224
Es muss dann sehr firefoxspezifisch sein. Entschuldigung für die Unannehmlichkeiten.
bebe
Warum sind das alles Sonderzeichen? Warum nicht einfach druckbares ASCII verwenden? (einfacher zu tippen, zuverlässiger und nur 1 Byte zum Golfen)
Cyoce
Dies funktioniert nicht wirklich, Mathda es kein .prototypeAttribut hat. Als Mathich das entfernte, schaffte ich es, dies auf ein 114-Byte-Snippet herunterzuspielen, das sie alle Einzelbyte-Buchstaben zuweist. Sie finden es hier .
ETHproductions
1
Sie können auch Golf spielen meine Lösung auf 106 Bytes auf Kosten auf den Bereich all diese Eigenschaften bewegter À- ÿ, die noch je 1 Byte in der ISO-8859-1 - Codierung (die JS unterstützt). In Firefox 50 setzt dies leider die .localeCompareMethode auf ×, aber das sollte normalerweise kein Problem sein. Quelle
ETHproductions
22

Das Umwandeln einer whileSchleife in eine forSchleife ist häufig äquivalent:

while(i--);
for(;i--;);

In der zweiten Form kann die Variableninitialisierung kombiniert werden:

i=10;while(i--);
for(i=10;i--;);

Beachten Sie, dass das zweite Formular ein Zeichen kürzer als das erste Formular ist.

mellamokb
quelle
6
Oder, noch besser, nur für Schleifen verwenden. Es gibt wirklich keinen Fall, in dem die Verwendung einer for-Schleife nach meiner Erfahrung zu größerem Code führt.
Isiah Meadows
22

Ausnahmefehler

Falls Zeichenketten- / Zeichenliterale nicht zulässig sind, können Sie einen try catch-Block verwenden:

try{something0}catch(e){str=e.message.split(0)[0]}

jetzt strgleich"something"

Wenn mehr Zeichenketten benötigt werden, können Sie diese mit einer Zahl verketten (zB Nullen).

try{something0foo0bar0}catch(e){arr=e.message.split(0)}

jetzt arrgleich["something", "foo", "bar", " is not defined"]

bebe
quelle
18

Wenn Sie eine Variable 1in jeder Iteration einer Schleife initialisieren (z. B. eine Variable in einer äußeren Schleife für eine innere Schleife zurücksetzen), wie folgt (aus meiner Antwort auf diese Frage ):

for(j=n-2;p=1,j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^

Da das Ergebnis einer Bedingung immer dann j++<=nist, 1wenn es wahr ist, können Sie die Bedingung einfach direkt der Variablen zuweisen (denn wenn sie falsch wird, wird die Schleife nicht mehr ausgeführt und spielt keine Rolle mehr):

for(j=n-2;p=j++<=n;r|=p)for(i=1;++i<j;)p=j%i?p:0;
          ^^^^^^^^

Normalerweise können Sie mit dieser Methode 2 Zeichen speichern . Grüße an @ugorenfür die Idee in den Kommentaren zu dieser Antwort.


In einem anderen Beispiel habe ich diesen Trick auch auf meine Antwort hier mit dem Ausdruck w=r=++c<S.lengthin meiner äußeren for-Schleife angewendet und insgesamt 4 Zeichen gespeichert.

mellamokb
quelle
18

Wenn Sie (für den Moment) bestimmte Spidermonkey-Skripte akzeptieren können, können Sie die Pfeilfunktionen von ECMAScript 6 verwenden . Anstatt wie folgt Code zu schreiben.

a.map(function(x){return x*2}) // function? return?

Sie können es so kürzen.

a.map(x=>x*2)
Konrad Borowski
quelle
17

Wenn Sie nach NaN suchen müssen, verwenden Sie nicht isNaN(x), sondern verwenden Sie x!=x, was kürzer ist und auch funktioniert.

if(isNaN(x)){
if(x!=x){

Beachten Sie, dass dies nur funktioniert, wenn typeof(x) === "number"; Wenn es sich zum Beispiel um eine Zeichenfolge handelt, wird isNaN("string")zurückgegeben true, aber "string" != "string"zurückgegeben false. Vielen Dank an Cyoce für diesen Hinweis!

ProgramFOX
quelle
2
Das ist eine geniale Verwendung dieser Eigenart. +1
ETHproductions
Achtung: diese ist nicht immer gleich: isNaN("string")Renditen true, während "string"!="string"Erträge false(natürlich)
Cyoce
@Cyoce Guter Punkt, danke! Ich habe meine Antwort bearbeitet.
ProgramFOX
In vielen Fällen können Sie sich sogar für entscheiden if(!x){, wenn Sie NaNexplizit erkennen.
Hohmannfan
1
Das Umsetzen xauf Nummer, +x!=+xentspricht isNaN(x), jedoch immer noch 2 Zeichen kürzer. Dann wird +"string"!=+"string"true zurückgegeben.
Tomas Langkaas
15

Array Summe / Produkt / Quotient

ES5 : 17 Bytes

eval(a.join('+'))

ES6 : 15 Bytes

eval(a.join`+`)

Natürlich können Sie das +für alles tauschen, was Sie wollen, zB *für ein Produkt oder einen /Quotienten.

George Reith
quelle
14

Verwenden Sie eine bitweise Operation, um eine Zahl auf Null zu runden:

// do this
T=Math.random()*6+1|0

// or do this
T=~~(Math.random()*6+1)

(Quelle: Zufälliges Würfelkippen )

Die Operatorrangfolge bestimmt, welche in Ihrem Programm kürzer ist.

PleaseStand
quelle
2
Dies kann auch verwendet werden, um eine Zeichenfolgeneingabe zu einer Ganzzahl zusammenzuführen, d n=prompt()|0. H.
Mellamokb
1
bitwise ist auch im Vergleich zu math.floor super schnell: jsperf.com/floor-vs-bitwise
vsync
@ Vsync: Seltsam. Ich bekomme math.floor auf Chrome 11.0.696.77 ungefähr doppelt so schnell wie bitweise.
Mellamokb
sehr merkwürdig. für mich sind sie beide mehr oder weniger gleich schnell und super schnell in Chrome, aber in FF ist die bitweise viel schneller als Chrome und Math.floorist furchtbar langsam ... sollte fast nicht verwendet werden, würde ich sagen.
vsync
Um die Kommentare auf dem neuesten Stand zu halten, sind sie im aktuellen Fx beide schnell und ungefähr gleich. Nicht, dass es im Vergleich zum umgebenden Code ein Engpass sein könnte ...
FireFly
14

Schleifentipp I

Sie können 1Zeichen beim Schleifen speichern , indem Sie idas zuletzt verwendete ändern :

//not so god
for(i=0;i<3;i++){
  alert(i);
}

//best
for(i=0;i<3;){
  alert(i++);
}

Hinweis: funktioniert auch mit --(aber ändern Sie die Schleife entsprechend, um Endlosschleifen zu vermeiden)


Looping Tip II

Es gibt bestimmte Szenarien, in denen Sie ein Zeichen speichern können, indem Sie mit dem inkrementierenden Operator und den Werten spielen:

for(i=0;i++<9;)
for(i=0;++i<10;)

Hinweis: Sie müssen zum Beispiel aufpassen, wenn 0 to -1. und 9 to 10, 99 to 100so lange herumspielen, bis Sie einen Weg finden, den Charakter zu retten

ajax333221
quelle
13

Verwenden Sie ^anstelle von !=oder== beim Vergleich mit einer Ganzzahl

//x!=3?a:b
  x^3?a:b

//x==3?a:b
  x^3?b:a

Ersetzen Sie Aufrufe der integrierten mathematischen Funktionen durch kürzere Ausdrücke

//Math.ceil(n)
  n%1?-~n:n

//Math.floor(n)
  ~~n
  0|n

//Math.abs(n)
  n<0?-n:n

//Math.round(n)
  n+.5|0

//Math.min(x,y)
  x<y?x:y

//Math.max(x,y)
  y<x?x:y
Tomas Langkaas
quelle
2
Alternativ können Sie -statt !=für ganze Zahlen auch einfach verwenden . Zum Beispiel n!=1?a:bwäre gleichbedeutend mitn-1?a:b
vrugtehagel
10

Bemerkenswert ist, dass Sie in einigen Fällen anstelle von Null eine Zeichenfolge verwenden können, um hier und da ein paar Bytes in Schleifen zu speichern:

s='';for(i=0;i++<9;)s+=i
for(i=s='';i++<9;)s+=i
// s="123456789", i=10
Dom Hastings
quelle
1
Ich habe "" ++ in der Konsole versucht und mich gefragt, ob es funktionieren würde, natürlich muss es zuerst in einer Variablen sein. Vielen Dank!
Vartan,
10

Sehr einfach, trotzdem hatte es niemand erwähnt.

Wenn Sie verwenden Math.min()oder Math.max()Sie können 6 Zeichen sparen, indem Sie dies tun:

Math.min(a,b)  // 13 chars
a<b?a:b        //  7 chars

Math.max(a,b)
a>b?a:b
António Almeida
quelle
10

Runden

Ich weiß, dass Alternativen Math.floor()gepostet wurden, aber was ist mit den anderen?

Bodenbelag:

Math.floor(x) //before
0|x           //after

Runden:

Math.round(x) //before
0|x+.5        //after

Decke:

Math.ceil(x) //before
x%1?-~x:x    //after - credits to @Tomas Langkaas
Mama Fun Roll
quelle
1
Beachten Sie, dass Sie 0|x+1einfach 1 addieren, wenn die Zahl, deren Obergrenze Sie ermitteln möchten, bereits eine Ganzzahl ist. Eine (meist) sichere Alternative ist 0|x+1-1e9, aber das ist nur drei Bytes kürzer.
ETHproductions
@ETHproductions meinst du nicht 0|x+1-1e-9?
Mama Fun Roll
Hoppla, ja. Vielen Dank für den Hinweis. (Aus irgendeinem Grund kann ich @ (Ihren Benutzernamen) nicht tun ...)
ETHproductions
Wahrscheinlich, weil meine Benutzernamen falsch geschrieben sind :)
Mama Fun Roll
1
Für die Decke x%1?-~x:x(9 Zeichen) ist eine bessere Alternative. Wie bei den Bodenbelägen 0|xund ~~xfunktioniert es jedoch nur bei positiven Zahlen.
Tomas Langkaas
9

In Fällen, in denen Sie den ternären Operator verwenden, um zwischen zwei Zahlen zu wählen , und die Bedingung entweder ein Boolescher Wert oder eine Zahl ist 1 or 0 , können Sie stattdessen mathematische Operationen ausführen:

(x ? num1 : num2) conclusions:

    1)if num1 equals num2, there ARE savings
    2)if num1 is (+1) or (-1) than num2, there ARE savings
    3)if either num1 or num2 equals to 0, there ARE savings
    4)it is MORE LIKELY to find greater savings on num1>num2 instead of num1<num2
    5)in method (*A) and (*B), savings are NOT GUARANTEED

    a)num1>num2
        i)(num1==(num2+1))
            ex1: (x?5:4) to (x+4)
            ex2: (x?8:7) to (x+7)
        ii)num2==0
            ex1: (x?3:0) to (x*3)
            ex2: (x?7:0) to (x*7)
        iii)
            (*A) or (*B) //one might be shorter

    b)num1<num2
        i)((num1+1)==num2)
            ex1: (x?4:5) to (5-x)
            ex2: (x?7:8) to (8-x)
        ii)num1==0
            ex1: (x?0:3) to (!x*3)
            ex2: (x?0:7) to (!x*7)
        iii)
            (*A) or (*B) //one might be shorter

    c)num1==num2
        i)
            ex1: (x?5:5) to (5)
            ex2: (x?-3:-3) to (-3)

    (*A) use ((x*(num1-num2))+num2)
        ex1: (x?8:4)   to ((x*4)+4)
        ex2: (x?4:8)   to ((x*-4)+8)

        ex3: (x?6:-4)  to ((x*10)-4)
        ex4: (x?-4:6)  to ((x*-10)+6)

        ex5: (x?4:-6)  to ((x*10)-6)
        ex6: (x?-6:4)  to ((x*-10)+4)

        ex7: (x?-5:-9) to ((x*4)-9)
        ex8: (x?-9:-5) to ((x*-4)-5)

    (*B) use ((!x*(num2-num1))+num1)
        ex1: (x?8:4)   to ((!x*-4)+8)
        ex2: (x?4:8)   to ((!x*4)+4)

        ex3: (x?6:-4)  to ((!x*-10)+6)
        ex4: (x?-4:6)  to ((!x*10)-4))

        ex5: (x?4:-6)  to ((!x*-10)+4)
        ex6: (x?-6:4)  to ((!x*10)-6)

        ex7: (x?-5:-9) to ((!x*-4)-5)
        ex8: (x?-9:-5) to ((!x*4)-9)

Hinweis: Zusätzlich zu diesem, müssen Sie den unnötigen entfernen 0-, +0, +-usw.

Hinweis 2: gibt es einen Einzelfall , wo (x) !== (x?1:0), wie xsein muss , typeof === "number"damit es funktioniert. In diesem Fall (-x)funktioniert es jedoch einwandfrei.

Hinweis 3: Wenn Sie keine Einsparungen finden, verwenden Sie einfach die erstere(x?y:z)

Früher dachte ich, dass Methode B niemals A schlagen könnte, es gibt jedoch Ausnahmen:

(x?97:100) //original

(-3*x+100)
(3*!x+97)

Ich habe ein Github-Projekt erstellt , das uns die Vereinfachung erleichtert ( jsFiddle-Demo )

mellamokb
quelle
@ ajax333221 void 0(es ist keine Funktion, sondern ein Schlüsselwort) ist kein Wert, es wird einfach zurückgegeben undefined.
Camilo Martin
@CamiloMartin Sie haben Recht, auch ich sehe jetzt den Punkt in dieser Antwort, amuss jedoch entweder 1 oder 0 sein, damit es funktioniert
ajax333221
@ ajax333221 Ja, eigentlich ist das Lustige am Code-Golfen für mich, dass die meisten der besten Tricks nur für das funktionieren, was Sie tun, und man fühlt sich so schlau, einen dieser Eckfälle mit Ecklösungen zu finden: D By the Art und Weise, die Sie nicht haben , um Kommentare zu löschen ...
Camilo Martin
9

tl; dr: Nutze ES6 Features!

Pfeilfunktionen

Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Beispiel:

s = x => x*x
// s = function (x) {
//   return x * x;
// }
Florent
quelle
Pfeilfunktionen wurden bereits am 13. Oktober 13 um 15:42 Uhr erwähnt . Aber das for... ofist cool. Noch kürzer als for each.. in.
Manatwork
2
Die Syntax für das Array-Verständnis scheint falsch zu sein. Gemäß der Dokumentation sollte wie in Python sein: b = [s(x) for (x of a)].
Manatwork
@manatwork Die obigen Beispiele laufen in Traceurs REPL
Florent am
Keine Ahnung von Traceur, aber Sie haben ECMAScript erwähnt und auf Mozilla-Dokumentation verwiesen. Das Array-Verständnis in keinem von ihnen sieht so aus, als hätten Sie es geschrieben.
Manatwork
1
Das Array-Verständnis wurde tatsächlich auf halbem Weg durchgezogen.
Isiah Meadows
9

Literale missbrauchen

Das aktuelle Beispiel: Prüfen Sie, ob "c"Groß- oder Kleinschreibung vorliegt, egal ob kein Buchstabe

"c"<{} // returns false, lower case
"C"<{} // returns true, upper case
l4m2
quelle
3
Wie funktioniert das?
Kühe quaken
2
@Cowsquack String({})gibt "[object Object]".
Dennis
8

So vergleichen Sie eine Zahl anhand der Umwandlung von Zahlen in Boolesche Werte:

Wenn Sie überprüfen wollen , wenn etwas zu einer gleich positiven Zahl , können Sie diesen Betrag abziehen und umgekehrt , was in dem war ifund elseBlöcke:

//simplified examples:
x==3?"y":"n"; <- 13 Chars
x-3?"n":"y"; <- 12 Chars

//expanded examples:
if(x==3){
    yes();
}else{
    no();
}

if(x-3){
    no();
}else{
    yes();
}

Und falls Sie mit einer negativen Zahl (* anders als -1) vergleichen möchten , müssen Sie nur diese Zahl addieren, anstatt sie zu subtrahieren.

* Nun, Sie können sicherlich verwenden x.indexOf(y) + 1, aber in dem speziellen Fall -1haben Sie die Möglichkeit, ~x.indexOf(y)stattdessen zu verwenden .

ajax333221
quelle
8

Verwenden Sie Mozillas nicht standardmäßige Funktion zum Schließen von Ausdrücken, um viele Zeichen in einem Skript zu speichern, die nur in den SpiderMonkey / Firefox- oder Rhino-Engines funktionieren müssen. Zum Beispiel,

function foo(){return bar}

wird

function foo()bar

Weitere Tricks finden Sie auf der Seite Stapelüberlauf.

PleaseStand
quelle
2
Das ist kein Javascript. Das ist eine RAUMSTATION !!!
Thomas Eding
1
ECMAScript 6 zur Rettung! ->bar
Ry
5
ECMAScript 6: let foo = () => bar;Ironischerweise kürzer als der oben genannte Golf-Code.
Isiah Meadows
1
ECMAScript 6: foo=_=>barnoch kürzer.
ETHproductions
Diese Verbindung ist unterbrochen.
Cyoce
8

Anstatt zu schreiben true, können Sie verwenden !0.

Wolle Vanillebär Lutz
quelle
4
Ebenso !1z false.
James M. Lay
10
Besser noch, verwenden Sie 1für trueund 0für false, es sei denn, Sie benötigen wirklich die wörtlichen Werte.
ETHproductions
8

Umwandlung in einen Booleschen Wert :

if(b){b=true}else{b=false}
b=b?true:false;
b=b?!0:!1;
b=!!b;

Hinweis: Dies ändert sich 0, "",false , null, undefinedund NaNzu false(alles andere true)

ajax333221
quelle