Quels conseils généraux avez-vous pour jouer au golf en JavaScript? Je recherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui soient au moins quelque peu spécifiques à JavaScript (par exemple, "supprimer les commentaires" n'est pas une réponse).
Remarque: Voir également des astuces pour le golf dans ECMAScript 6 et versions ultérieures.
code-golf
tips
javascript
mellamokb
la source
la source
var
? Et le code de golf JavaScript doit-il être une fonction ou produire quelque chose directement? Honnêtement, je pense que cela peut faire beaucoup de différence.Réponses:
Fantaisie pour les boucles
vous pouvez utiliser la norme pour la boucle de manière non standard
est essentiellement équivalent à:
Un bon truc consiste donc à écrire votre code avec une
while
boucle, puis à le scinder en plusieursa,b,c
partiesfor
.Quelques exemples que j'ai écrits :
Enchaîner vos setters
Si vous initialisez ou réinitialisez plusieurs valeurs, enchaînez la valeur à toutes les variables qui en ont besoin:
Casting implicite
Ne vérifiez pas vos types, utilisez-les tels quels.
parseInt()
coûts de10
caractères. Si vous avez besoin de sortir d'une chaîne, soyez créatif:Évitez les points-virgules
JavaScript a une insertion automatique de point-virgule. Utilisez-le souvent et bien.
Une ligne
Économisez sur les crochets en plaçant autant que possible en lignes simples ou paramètres:
Opérateurs d'incrémentation / décrémentation
et
peut facilement être réécrit comme
et
respectivement.
Utiliser
this
ouself
au lieu dewindow
dans un contexte globalÉconomies explicites de 2 caractères.
Utiliser la notation entre crochets pour l'accès aux propriétés répétées
Il s’agit bien d’un équilibre entre la longueur du nom de la propriété et le nombre d’accès. Au lieu d'appeler
a.longFunctionName()
deux fois avec la notation par points, il est plus court d'enregistrer le nom et d'appeler la fonction via la notation entre crochets:-contre-
Ceci est particulièrement efficace avec des fonctions telles
document.getElementById
que celles pouvant être réduites àd[e]
.Remarque:
Avec la notation entre crochets, le coût est
6 + name.length
la première fois en caractères. Chaque accès ultérieur a un coût de3
caractères.Pour la notation par points, tous les accès coûtent
name.length + 1
(+1 pour les.
) caractères.Utilisez cette méthode si
6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)
.len = longueur du nom de la propriété
i = accès minimum à exploiter
Le nombre d'accès peut également couvrir plusieurs objets. Si vous accédez au moins
.length
4 fois sur des tableaux différents, vous pouvez utiliser la même variable contenant la chaîne'length'
.la source
c = ~~a-~~b
devrait êtrec = ~~a+~~b
. En outre, vous pouvez implicitement transtyper en entier en utilisant|0
, par exempleMath.random()*6|0
.a
etb
sont des chaînes, vous pouvez faire+a+b
pour convertir en nombre et les ajouter.d- -b
un jour mon code ...a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Fractionner avec des nombres pour sauvegarder les guillemets:
la source
.split`...`
"alpha,bravo,charlie".split`,`
Utilisez l'opérateur virgule pour éviter les accolades ( s'applique également à C ):
Au lieu de
qui est un caractère plus long.
la source
Génération de nombres aléatoires plus courte
Si vous avez besoin d'un booléen aléatoire (
0
ou1
):Si vous avez besoin d'un entier aléatoire
0 <= n < 1337
:Cela fonctionne car a
Date
est stocké en interne dans JavaScript sous forme de millisecondes depuis une époque. Ilnew Date
est donc forcé de le faire123somebignumber456
lorsque vous essayez de faire un calcul de nombre entier dessus.Bien sûr, ces nombres "aléatoires" ne le seront pas vraiment, surtout si vous les appelez plusieurs fois de suite, gardez cela à l'esprit.
la source
Vous pouvez utiliser la forme littérale d'objet de get / set pour éviter d'utiliser le mot-clé
function
.la source
Celui-ci est moins connu et moins utilisé, mais peut être impressionnant s'il est utilisé dans la bonne situation. Considérons une fonction qui ne prend aucun argument et retourne toujours un nombre différent à l'appel, et le nombre retourné sera utilisé dans un calcul:
Vous pouvez normalement raccourcir cette fonction en utilisant un nom de variable à une lettre:
Un meilleur moyen de réduire la longueur consiste à abuser
valueOf
, ce qui vous permet d'économiser 2 caractères par invocation. Utile si vous appelez la fonction plus de 5 fois:la source
let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)
oulet a=Array(7).map((_,i)=>i*Math.random()|0+5)
, 36 ou 42 octets enregistrés, respectivement.r()
ou de le raccourcir?r={valueOf:Math.random}
C'est juste du génie: DProfiter des opérateurs de court-circuit
Plutôt que de longues
if
déclarations ou l'utilisation d'opérateurs ternaires, vous pouvez utiliser&&
et||
raccourcir votre code. Par exemple:peut devenir
L’
||
opérateur est souvent utilisé de cette manière pour définir les valeurs par défaut:C'est la même chose que d'écrire
Création de chaînes répétitives à l'aide de Array
Si vous souhaitez initialiser une longue chaîne d'un caractère particulier, vous pouvez le faire en créant un tableau de n + 1 , où n est le nombre de fois où vous souhaitez répéter le caractère:
Plus la chaîne est grosse, plus le gain est important.
Numéros d'analyse
Utilisez les opérateurs
+
et à la~
place deparseFloat()
ouparseInt()
lors de la fusion d'un type de chaîne qui n'est qu'un nombre à un type de nombre:Méfiez-vous cependant, d'autres types peuvent être fusionnés avec ces opérateurs (par exemple,
true
deviendraient1
), une chaîne vide ou une chaîne contenant uniquement des espaces deviendrait0
. Cela pourrait toutefois être utile dans certaines circonstances.la source
str.repeat(count)
Faufiler l'initialisation d'une variable dans l'appel prompt () pour obtenir une entrée utilisateur
à la place d'utiliser
En tant qu'effet secondaire, il affiche la valeur d'entrée dans la fenêtre d'invite tout en enregistrant 1 caractère.
la source
[1,2,3].join('',i=5)
dans les cas où elle enregistre une paire d'accolades.i=5,[1,2,3].join()
.Combinez les boucles imbriquées:
Exemple avec différentes valeurs pour
i
/j
:la source
i*j
et les opérateurs de division / module récupèrent les valeurs individuelles dei
etj
.Raccourcis Unicode
Si vous utilisez une propriété intégrée dans un grand défi de golf, vous pouvez aliaser chaque propriété avec un équivalent d'un personnage:
Après avoir exécuté le code ci-dessus, vous pouvez l'utiliser comme ceci:
"foo".Č(/.*/,'bar') // replaces foo with bar
Cela coûte 118 octets, donc cela peut ne pas être utile dans certaines situations
Cela peut dépendre du navigateur et je ne sais pas s'il est plus court
with(Array){join(foo),...}
ou si les variables sont définies comme propriétés utilisées,with(Array){j=join,m=map...}
mais ça vaut la peine de le mentionner.la source
Math
parce qu'il n'a pas d'.prototype
attribut. En supprimantMath
, cependant, j’ai réussi à en faire un extrait de 114 octets qui les assigne tous à des lettres à un octet. Vous pouvez le trouver ici .À
-ÿ
, qui correspond toujours à 1 octet dans le codage ISO-8859-1 (pris en charge par JS). Dans Firefox 50, la.localeCompare
méthode est malheureusement activée×
, mais cela ne devrait généralement pas être un problème. sourceConvertir une
while
boucle enfor
boucle est souvent équivalent:Mais la seconde forme peut avoir une initialisation variable combinée:
Notez que la deuxième forme est un caractère plus court que la première.
la source
Exception abuser
au cas où les littéraux chaîne / caractère sont interdits, vous pouvez utiliser un bloc try catch:
maintenant
str
égale"something"
si plus de chaînes sont nécessaires, vous pouvez les chaîner avec un nombre (par exemple, des zéros)
maintenant
arr
égale["something", "foo", "bar", " is not defined"]
la source
Si vous initialisez une variable à
1
chaque itération d'une boucle (par exemple, en réinitialisant une variable dans une boucle externe pour une boucle interne), procédez comme suit (tiré de ma réponse à cette question ):Puisque le résultat d'une condition comme
j++<=n
est1
chaque fois que sa valeur est true, vous pouvez simplement affecter la condition directement à la variable (car lorsqu'elle devient false, la boucle cessera de s'exécuter et n'aura plus d'importance):Vous pouvez généralement enregistrer 2 caractères en utilisant cette méthode. En ce qui
@ugoren
concerne l'idée dans les commentaires à cette réponse.Pour un autre exemple, j’ai également appliqué cette astuce à ma réponse ici avec l’expression figurant
w=r=++c<S.length
dans ma boucle for externe, en sauvegardant au total 4 caractères.la source
Si vous pouvez accepter des scripts spécifiques à Spidermonkey (pour le moment), vous pouvez utiliser les fonctions de flèche ECMAScript 6 . Au lieu d'écrire du code comme suit.
Vous pouvez le raccourcir comme ça.
la source
Si vous avez besoin de vérifier NaN, n'utilisez pas
isNaN(x)
, mais utilisezx!=x
qui est plus court et qui fonctionne aussi.Notez que cela ne fonctionne que si
typeof(x) === "number"
; si c'est une chaîne par exemple,isNaN("string")
retournetrue
, mais"string" != "string"
retournefalse
. Merci à Cyoce de l'avoir signalé!la source
isNaN("string")
retournetrue
, alors que"string"!="string"
retournefalse
(évidemment)if(!x){
, si vous détectezNaN
explicitement.x
en nombre, le+x!=+x
rend équivalent àisNaN(x)
2 caractères plus courts. Ensuite,+"string"!=+"string"
retourne vrai.Tableau somme / produit / quotient
ES5 : 17 octets
ES6 : 15 octets
Bien sûr, vous pouvez échanger le
+
pour tout ce que vous voulez, par exemple*
pour un produit ou/
un quotient.la source
Utilisez une opération au niveau des bits pour arrondir un nombre vers zéro:
(Source: basculement aléatoire des dés )
La priorité de l'opérateur détermine laquelle sera la plus courte dans votre programme.
la source
n=prompt()|0
.Math.floor
est terriblement lent ... la plupart ne devraient pas être utilisés, je dirais.Astuce en boucle I
Vous pouvez sauvegarder un
1
caractère en boucle en modifianti
le dernier temps utilisé:Remarque: fonctionne avec
--
aussi (mais modifiez la boucle en conséquence pour éviter une boucle infinie)Looping Tip II
Il existe certains scénarios dans lesquels vous pouvez enregistrer un personnage en jouant avec l'opérateur et les valeurs d'incrémentation:
Remarque: vous devez faire attention lorsque, par exemple
0 to -1
. et9 to 10, 99 to 100
, alors jouez jusqu'à ce que vous trouviez un moyen de sauver le personnagela source
Utiliser
^
au lieu de!=
ou==
en comparant à un entierRemplacer les appels aux fonctions mathématiques intégrées par des expressions plus courtes
la source
-
au lieu de!=
pour les entiers; Par exemple,n!=1?a:b
serait équivalent àn-1?a:b
Il est intéressant de noter que vous pouvez utiliser une chaîne à la place de zéro dans certains cas pour sauvegarder quelques octets ici et là dans des boucles:
la source
Très simple, même ainsi, personne n'en avait parlé.
Si vous utilisez
Math.min()
ouMath.max()
vous pouvez enregistrer 6 caractères en procédant comme suit:la source
Arrondi
Je sais que des alternatives à
Math.floor()
ont été postées, mais qu'en est-il des autres?Sol:
Arrondi:
Plafond:
la source
0|x+1
simplement ajoute 1 si le nombre dont vous voulez trouver le plafond est déjà un entier. Une alternative (généralement) sûre est0|x+1-1e9
, mais ce n'est que trois octets plus court.0|x+1-1e-9
?x%1?-~x:x
(9 caractères) est une meilleure alternative. Cependant, comme les alternatives de sol0|x
et~~x
, il ne fonctionne que pour les nombres positifs.Dans les cas où vous utilisez l'opérateur ternaire pour choisir entre deux nombres et que le conditionnel est un booléen ou un nombre
1 or 0
, vous pouvez effectuer des opérations mathématiques à la place:Remarque: En plus de cela, vous devrez supprimer l'inutile
0-
,+0
,+-
etc.Note 2: il existe un cas isolé où
(x) !== (x?1:0)
, commex
il se doittypeof === "number"
pour que cela fonctionne. Cependant, dans le cas de(-x)
cela fonctionne très bien.Note3: Si vous ne trouvez pas d’épargne, utilisez simplement l’ancien
(x?y:z)
Auparavant, je pensais que la méthode B ne pourrait jamais battre A, bien que des exceptions existent:
J'ai créé un projet github qui nous simplifie la tâche ( démo jsFiddle )
la source
void 0
(ce n'est pas une fonction, mais un mot clé) n'est pas une valeur, il retourne simplementundefined
.a
doit êtretl; dr: Utilisez les fonctionnalités de l'ES6!
Fonctions de flèche
Doc: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Exemple:
la source
for
..of
c'est cool. Même plus courte quefor each
..in
.b = [s(x) for (x of a)]
.Abuser des littéraux
Exemple récent: Vérifiez si
"c"
les lettres sont majuscules ou minuscules, peu importe la lettrela source
String({})
donne"[object Object]"
.Comment comparer un nombre avec l'aide de comment les nombres se transforment en booléens:
Si vous voulez vérifier si quelque chose est égal à un nombre positif , vous pouvez soustraire ce montant et inverser ce qui était à l'intérieur des blocs
if
etelse
:Et au cas où vous voudriez comparer avec un nombre négatif (* différent de
-1
), il vous suffit simplement d’ ajouter ce nombre au lieu de le soustraire.* Bien, vous pouvez sûrement utiliser
x.indexOf(y) + 1
, mais dans le cas particulier de-1
vous avez la possibilité d'utiliser à la~x.indexOf(y)
place.la source
Utilisez la fonctionnalité non standard de "fermeture d’expression" de Mozilla pour enregistrer dans un script de nombreux caractères devant uniquement fonctionner dans les moteurs SpiderMonkey / Firefox ou Rhino. Par exemple,
devient
Voir la page Dépassement de pile pour plus de telles astuces.
la source
->bar
let foo = () => bar;
ironiquement plus court que le code golfé ci-dessus.foo=_=>bar
même plus court.Utiliser
if(~a.indexOf(b))
au lieu deif(a.indexOf(b)!=-1)
la source
Au lieu d'écrire,
true
vous pouvez utiliser!0
.la source
!1
pourfalse
.1
pourtrue
et0
pourfalse
, sauf si vous avez vraiment besoin des valeurs littérales.Transformation en booléen :
Note: Cela change
0
,""
,false
,null
,undefined
etNaN
àfalse
(tout le restetrue
)la source