Jakie masz ogólne wskazówki dotyczące gry w golfa w JavaScript? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej w pewnym stopniu specyficzne dla JavaScript (np. „Usuń komentarze” nie jest odpowiedzią).
Uwaga: Zobacz także Porady dotyczące gry w golfa w ECMAScript 6 i nowszych
code-golf
tips
javascript
mellamokb
źródło
źródło
var
)? I czy kod JavaScript do golfa powinien być funkcją, czy wyświetlać coś bezpośrednio? Szczerze uważam, że może to mieć duże znaczenie.Odpowiedzi:
Fancy For Loops
możesz użyć standardowej pętli dla niestandardowych sposobów
jest zasadniczo równoważny z:
więc dobrą sztuczką jest napisanie kodu w
while
pętli, a następnie podzielenie go naa,b,c
części wfor
pętli.Kilka przykładów , które napisałem :
Połącz swoje setery
Jeśli inicjujesz lub resetujesz wiele wartości, połącz wartość ze wszystkimi potrzebnymi zmiennymi:
Implicit Casting
Nie sprawdzaj typów, po prostu używaj ich takimi, jakie są.
parseInt()
kosztuje10
postacie. Jeśli chcesz odrzucić ciąg, bądź kreatywny:Unikaj średników
JavaScript ma automatyczne wstawianie średników. Używaj go często i dobrze.
Jednowarstwowe
Zaoszczędź na nawiasach, umieszczając jak najwięcej w pojedynczych wierszach lub parametrach:
Operatory inkrementacji / dekrementacji
i
można łatwo przepisać jako
i
odpowiednio, kolejno.
Użyj
this
lubself
zamiastwindow
w kontekście globalnymoczywiste oszczędności 2 znaków.
Użyj notacji w nawiasach, aby uzyskać dostęp do powtarzanych właściwości
Jest to z pewnością równowaga między długością nazwy nieruchomości a liczbą dostępów. Zamiast wywoływać
a.longFunctionName()
dwukrotnie notację kropkową, krótsze jest zapisanie nazwy i wywołanie funkcji za pomocą notacji nawiasowej:-vs-
jest to szczególnie skuteczne w przypadku funkcji,
document.getElementById
które można zredukować dod[e]
.Uwaga:
Przy zapisie w nawiasie
6 + name.length
za pierwszym razem koszt to znaki. Każdy kolejny dostęp ma koszt3
znaków.W przypadku notacji kropkowej wszystkie wejścia kosztują
name.length + 1
(+1 dla.
) znaków.Użyj tej metody, jeśli
6 + name.length + (3 * (accesses - 1)) < accesses * (name.length + 1)
.len = długość nazwy właściwości
i = minimalny dostęp, aby skorzystać
Liczba dostępów może również obejmować wiele obiektów. Jeśli uzyskujesz dostęp
.length
4 lub więcej razy na różnych tablicach, możesz użyć tej samej zmiennej przechowującej ciąg'length'
.źródło
c = ~~a-~~b
powinno byćc = ~~a+~~b
. Ponadto możesz|0
na przykład niejawnie rzutować na liczbę całkowitą, używającMath.random()*6|0
.a
ib
są ciągami, możesz zrobić,+a+b
aby przekonwertować na liczbę i dodać je.d- -b
w moim kodzie ...a.f=a.longfunctionname;a.f(b);a.f(c);a.f(d)
Dzielenie liczbami, aby zapisać cytaty:
źródło
.split`...`
"alpha,bravo,charlie".split`,`
Użyj operatora przecinka, aby uniknąć nawiasów klamrowych ( dotyczy również C ):
Zamiast
który jest o jedną postać dłuższy.
źródło
Krótsze generowanie liczb losowych
Jeśli potrzebujesz losowej wartości logicznej (
0
lub1
):Jeśli potrzebujesz losowej liczby całkowitej
0 <= n < 1337
:Działa to, ponieważ a
Date
jest przechowywane wewnętrznie w JavaScript jako ilość milisekund od epoki, więcnew Date
jest przymuszane,123somebignumber456
gdy próbujesz wykonać na nim matematykę całkowitą.Oczywiście te „losowe” liczby naprawdę nie będą tak losowe, zwłaszcza jeśli wywołujesz je wiele razy w krótkich odstępach czasu, więc miej to na uwadze.
źródło
Możesz użyć dosłownej formy obiektu get / set, aby uniknąć używania słowa kluczowego
function
.źródło
Ten jest mniej znany i rzadziej używany, ale może być imponujący, jeśli zostanie użyty we właściwej sytuacji. Rozważ funkcję, która nie przyjmuje argumentów i zawsze zwraca inną liczbę po wywołaniu, a zwrócona liczba zostanie wykorzystana w obliczeniach:
Zwykle możesz skrócić tę funkcję, używając jednuliterowej nazwy zmiennej:
Lepszym sposobem na zmniejszenie długości jest nadużycie
valueOf
, co daje oszczędność 2 znaków na każde wywołanie. Przydatne, jeśli wywołasz funkcję więcej niż 5 razy:źródło
let a=[5,6,7,8,9,10,11,12].map(x=>x*Math.random()|0)
lub odpowiedniolet a=Array(7).map((_,i)=>i*Math.random()|0+5)
36 lub 42 bajty.r()
lub skrócić?r={valueOf:Math.random}
To po prostu genialne: DWykorzystanie operatorów zwarć
Zamiast długich
if
instrukcji lub operatorów trójskładnikowych możesz użyć&&
i||
skrócić swój kod. Na przykład:może zostać
||
Operator jest często używany w ten sposób do ustawiania wartości domyślnych:To jest tak samo jak pisanie
Tworzenie powtarzających się ciągów za pomocą Array
Jeśli chcesz zainicjować długi ciąg określonego znaku, możesz to zrobić, tworząc tablicę o długości n + 1 , gdzie n jest liczbą powtórzeń znaku:
Im większy ciąg, tym większa oszczędność.
Parsowanie liczb
Użyj operatorów
+
i~
zamiastparseFloat()
lubparseInt()
podczas koalescencji typu ciągu, który jest tylko liczbą do typu liczby:Uważaj jednak, inne typy mogą być łączone z tymi operatorami (na przykład
true
mogłyby stać się1
) pustym łańcuchem lub łańcuchem zawierającym tylko białe znaki0
. Może to jednak być przydatne w pewnych okolicznościach.źródło
str.repeat(count)
Podejmij inicjalizację zmiennej do wywołania prompt () w celu uzyskania danych wejściowych od użytkownika
zamiast używać
Jako efekt uboczny wyświetla wartość wejściową w oknie zachęty, zapisując 1 znak.
źródło
[1,2,3].join('',i=5)
w przypadkach, gdy zapisuje parę nawiasów klamrowych.i=5,[1,2,3].join()
.Połącz zagnieżdżone dla pętli:
Przykład z różnymi wartościami
i
/j
:źródło
i*j
a operatory podziału / modułu pobierają indywidualne wartościi
ij
.Skróty Unicode
Jeśli używasz piekielnie wbudowanej nieruchomości podczas dużego wyzwania golfowego, możesz aliasować każdą właściwość do ekwiwalentu jednej postaci:
Po wykonaniu powyższego kodu możesz go użyć w następujący sposób:
"foo".Č(/.*/,'bar') // replaces foo with bar
Kosztuje to 118 bajtów, więc może nie być przydatne w niektórych sytuacjach
Może być zależny od przeglądarki i nie jestem pewien, czy jest krótszy
with(Array){join(foo),...}
lub definiuje zmienne jako używane właściwości,with(Array){j=join,m=map...}
ale nadal warto o tym wspomnieć.źródło
Math
ponieważ nie ma.prototype
atrybutu.Math
Jednak po usunięciu udało mi się zagrać w golfa do fragmentu o długości 114 bajtów, który przypisuje je wszystkim jednobajtowym literom. Możesz go znaleźć tutaj .À
-ÿ
który jest nadal 1 bajtem w kodowaniu ISO-8859-1 (który obsługuje JS). W przeglądarce Firefox 50.localeCompare
metoda ta jest niestety włączona×
, ale zwykle nie powinno to stanowić problemu. źródłoPrzekształcanie
while
pętli wfor
pętlę jest często równoważne:Ale druga forma może mieć zmienną inicjalizację połączoną:
Zauważ, że druga forma jest o jeden znak krótsza niż pierwsza forma.
źródło
Nadużywanie wyjątków
w przypadku, gdy literały łańcuchowe / znakowe są zabronione, możesz użyć bloku try catch:
teraz
str
jest równy"something"
jeśli potrzeba więcej ciągów, możesz połączyć go łańcuchem z liczbą (np. zerami)
teraz
arr
jest równy["something", "foo", "bar", " is not defined"]
źródło
Jeśli inicjujesz zmienną
1
w każdej iteracji pętli (na przykład resetujesz zmienną w zewnętrznej pętli dla wewnętrznej pętli), wykonaj następujące czynności (z mojej odpowiedzi na to pytanie ):Ponieważ wynikiem warunku podobnego
j++<=n
jest1
zawsze, gdy jest on prawdziwy, możesz po prostu przypisać warunek bezpośrednio do zmiennej (ponieważ gdy stanie się fałszem, pętla przestanie działać i nie będzie już miała znaczenia):Za pomocą tej metody można zwykle zapisać 2 znaki . Odnosi się
@ugoren
do pomysłu w komentarzach do tej odpowiedzi.W innym przykładzie zastosowałem tę sztuczkę do mojej odpowiedzi tutaj z wyrażeniem
w=r=++c<S.length
w mojej zewnętrznej pętli for, oszczędzając w sumie 4 znaki.źródło
Jeśli możesz zaakceptować określone skrypty Spidermonkey (na razie), możesz użyć funkcji strzałek ECMAScript 6 . Zamiast pisać kod jak poniżej.
Możesz to skrócić w ten sposób.
źródło
Jeśli potrzebujesz sprawdzić NaN, nie używaj
isNaN(x)
, ale używajx!=x
, który jest krótszy i działa.Zauważ, że działa to tylko, jeśli
typeof(x) === "number"
; jeśli jest to na przykład ciąg znaków,isNaN("string")
zwracatrue
, ale"string" != "string"
zwracafalse
. Dziękujemy Cyoce za zwrócenie na to uwagi!źródło
isNaN("string")
zwracatrue
, natomiast"string"!="string"
zwracafalse
(oczywiście)if(!x){
, jeśli wykrywaszNaN
jawnie.x
na liczbę+x!=+x
powoduje, że jest to równoważneisNaN(x)
, ale wciąż o 2 znaki krótsze. Następnie+"string"!=+"string"
zwraca true.Suma tablicowa / produkt / iloraz
ES5 : 17 bajtów
ES6 : 15 bajtów
Oczywiście możesz zamienić
+
na dowolne, np.*
Na produkt lub/
iloraz.źródło
Użyj operacji bitowej, aby zaokrąglić liczbę w kierunku zera:
(Źródło: Losowe przechylanie kości )
Priorytet operatora określa, który program będzie krótszy.
źródło
n=prompt()|0
.Math.floor
jest strasznie powolna .. prawie nie należy używać, powiedziałbym.Looping Tip I
Możesz zapisać
1
postać podczas zapętlania, zmieniająci
ostatnio używane:Uwaga: działa
--
również z (ale odpowiednio zmodyfikuj pętlę, aby uniknąć nieskończonego zapętlenia)Looping Tip II
Istnieją pewne scenariusze, w których można zapisać jedną postać, grając z operatorem i wartościami:
Uwaga: na przykład musisz zwrócić uwagę
0 to -1
. i9 to 10, 99 to 100
, więc baw się, aż znajdziesz sposób na uratowanie postaciźródło
Użyj
^
zamiast!=
lub==
podczas porównywania z liczbą całkowitąZastąp wywołania wbudowanych funkcji matematycznych krótszymi wyrażeniami
źródło
-
zamiast!=
liczb całkowitych; Na przykładn!=1?a:b
byłoby równoważne zn-1?a:b
Warto zauważyć, że w niektórych przypadkach można użyć ciągu zamiast zera, aby zapisać kilka bajtów tu i tam w pętlach:
źródło
Mimo to bardzo prosty, nikt o tym nie wspominał.
Jeśli używasz
Math.min()
lubMath.max()
możesz zapisać 6 znaków, robiąc to:źródło
Zaokrąglanie
Wiem, że
Math.floor()
opublikowano alternatywy , ale co z pozostałymi?Posadzka:
Zaokrąglanie:
Sufit:
źródło
0|x+1
dodaje 1, jeśli liczba, dla której chcesz znaleźć pułap, jest już liczbą całkowitą. Jest (przeważnie) bezpieczna alternatywa0|x+1-1e9
, ale jest to tylko trzy bajty krótsze.0|x+1-1e-9
?x%1?-~x:x
(9 znaków) jest lepszą alternatywą. Jednak, podobnie jak alternatyw podłogowych0|x
i~~x
to działa tylko dla liczb dodatnich.W przypadkach, gdy używasz operatora trójskładnikowego do wybierania między dwiema liczbami , a warunek jest albo wartością logiczną, albo liczbą
1 or 0
, możesz zamiast tego wykonać operacje matematyczne:Uwaga: Poza tym, trzeba będzie usunąć zbędne
0-
,+0
,+-
itd.Uwaga 2: istnieje izolowany przypadek, w którym
(x) !== (x?1:0)
, jakx
trzeba , musitypeof === "number"
działać. Jednak w przypadku(-x)
tego działa dobrze.Uwaga 3: Jeśli nie znajdziesz oszczędności, po prostu skorzystaj z pierwszej
(x?y:z)
Wcześniej myślałem, że metoda B nigdy nie pokona A, jednak istnieją wyjątki:
Stworzyłem projekt github, który upraszcza dla nas ( demo jsFiddle )
źródło
void 0
(to nie jest funkcja, ale słowo kluczowe) nie jest wartością, po prostu zwracaundefined
.a
musi to być 1 lub 0, aby zadziałałotl; dr: Użyj funkcji ES6!
Funkcje strzałek
Dokument: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/arrow_functions
Przykład:
źródło
for
..of
jest fajne. Nawet krótszy niżfor each
..in
.b = [s(x) for (x of a)]
.Nadużycie literałów
Ostatnia próbka: Sprawdź, czy
"c"
wielkie lub małe litery, nie ma znaczenia, jeśli nie literaźródło
String({})
daje"[object Object]"
.Jak porównać liczbę za pomocą tego, jak liczby zamieniają się w logiczne:
Jeśli zamierzasz sprawdzić, czy coś jest równe liczbie dodatniej , możesz odjąć tę kwotę i odwrócić to, co było w blokach
if
ielse
:A jeśli chcesz porównać z liczbą ujemną (* inną niż
-1
), po prostu musisz dodać tę liczbę zamiast odejmować.* cóż, z pewnością możesz użyć
x.indexOf(y) + 1
, ale w szczególnym przypadku-1
masz możliwość korzystania~x.indexOf(y)
zamiast niego.źródło
Użyj niestandardowej funkcji „zamykania wyrażeń” Mozilli, aby zapisać wiele znaków w skrypcie, który musi działać tylko w silnikach SpiderMonkey / Firefox lub Rhino. Na przykład,
staje się
Zobacz stronę Przepełnienie stosu, aby uzyskać więcej takich sztuczek.
źródło
->bar
let foo = () => bar;
ironicznie krótszy niż kod w golfa powyżej.foo=_=>bar
jeszcze krótszy.Użyj
if(~a.indexOf(b))
zamiastif(a.indexOf(b)!=-1)
źródło
Zamiast pisać
true
możesz użyć!0
.źródło
!1
dlafalse
.1
dlatrue
i0
dlafalse
, chyba że naprawdę potrzebujesz literalnych wartości.Przekształcanie w wartość logiczną :
Uwaga: To zmienia
0
,""
,false
,null
,undefined
iNaN
nafalse
(wszystko innetrue
)źródło