태그 보관물: javascript

javascript

ECMAScript 6 이상에서의 골프 팁 않습니다. 반면 ES6 +에는

이것은 다른 “<…>에서의 골프 팁”과 유사하지만 특히 ECMAScript 6 이상에서 제공되는 JavaScript의 새로운 기능을 대상으로합니다.

JavaScript는 본질적으로 매우 장황한 언어입니다. function(){}, .forEach()문자열을 배열로 변환, 배열 같은 객체를 배열로 변환하는 등은 부풀려서 골프에 적합하지 않습니다.

반면 ES6 +에는 매우 편리한 기능과 설치 공간이 줄었습니다. x=>y, [...x], 등 그냥 예 중 일부입니다.

코드에서 여분의 몇 바이트를 제거하는 데 도움이되는 몇 가지 유용한 트릭을 게시하십시오.

참고 : ES5에 대한 트릭 은 JavaScript의 골프 팁 에서 이미 사용 가능합니다 . 이 스레드에 대한 답변은 ES6 및 기타 향후 ES 버전에서만 사용 가능한 트릭에 중점을 두어야합니다.

그러나이 스레드는 현재 ES5 기능을 사용하여 골프를 타는 사용자를위한 것입니다. 답변에는 ES6 기능을 이해하고 자신의 ES5 코딩 스타일에 매핑하는 데 도움이되는 팁도 포함될 수 있습니다.



답변

스프레드 연산자 ...

스프레드 연산자는 배열 값을 쉼표로 구분 된 목록으로 변환합니다.

사용 사례 1 :

함수가 목록을 기대하는 배열을 직접 사용하십시오.

list=[1,2,3]
x=Math.min(...list)
list=[10,20], a.push(...list) // similar to concat()

사용 사례 2 :

iterable (일반적으로 문자열)에서 배열 리터럴을 만듭니다.

[...'buzzfizz'] // -> same as .split('')

사용 사례 3 :

함수에 대한 가변 개수의 인수를 선언

F=(...x) => x.map(v => v+1)
// example: F(1,2,3) == [2,3,4]

모질라 문서보기


답변

내가 가입 한 이후로 트릭을 배웠다

내 주요 프로그래밍 언어는 JS이며 대부분 ES6입니다. 일주일 전이 사이트에 가입 한 이후, 동료 회원들로부터 많은 유용한 트릭을 배웠습니다. 나는 여기에 그 중 일부를 결합하고 있습니다. 커뮤니티에 대한 모든 크레딧.

화살표 함수 및 루프

우리는 화살표 기능이 많은 바이트를 절약한다는 것을 알고 있습니다.

function A(){do something} // from this
A=a=>do something // to this

하지만 몇 가지를 명심해야합니다

  • 사용 클럽 여러 제표에 대한 시도 ,즉, (a=b,a.map(d))반환되는 값이 마지막 표현이다, 여기에서 –a.map(d)
  • 귀하의 경우 do something부분은 하나 이상의 문입니다, 당신은 주변에 추가해야 {}브래킷.
  • {}대괄호 가 있으면 명시적인 return 문을 추가해야합니다.

위의 내용은 루프가 관련된 많은 경우에 적용됩니다. 그래서 같은 :

u=n=>{for(s=[,1,1],r=[i=1,l=2];c=l<n;i+=!c?s[r[l++]=i]=1:1)for(j of r)c-=j<i/2&s[i-j];return n>1?r:[1]}

여기에서 반환으로 인해 9 자 이상을 낭비하고 있습니다. 이것은 최적화 될 수 있습니다.

  • for 루프를 피하십시오. 사용 .map하거나 .every또는 .some대신. 매핑하는 것과 동일한 어레이를 변경하려는 경우 실패합니다.
  • 루프를 폐쇄 화살표 함수로 감싸서 기본 화살표 함수를 단일 명령문으로 변환하십시오.

위의 내용은 다음과 같습니다.

u=n=>(s=>{for(r=[i=1,l=2];c=l<n;i+=!c?s[r[l++]=i]=1:1)for(j of r)c-=j<i/2&s[i-j]})([,1,1])|n>1?r:[1]

제거 된 문자 : {}return

추가 된 문자 : (){}>|

변수를 올바르게 채우는 클로저 메소드를 호출 n한 다음 클로저 메소드가 아무것도 리턴하지 않기 때문에 (즉, 리턴 undefined), 비트 단위 또는 n외부 화살표 함수의 단일 명령문으로 배열을 모두 리턴합니다.u

쉼표와 세미콜론

지금까지의 것을 피하십시오.

루프에서 변수를 선언하거나 이전 섹션에서 언급 한 것과 같이 ,분리 된 명령문을 사용하여 단일 명령문 화살표 기능을 사용하는 경우,이를 피 ,하거나 ;마지막 몇 바이트를 제거 하기 위해 약간의 멋진 트릭을 사용할 수 있습니다 .

이 코드를 고려하십시오.

r=v=>Math.random()*100|0;n=r();m=r();D=v=>A(n-x)+A(m-y);d=0;do{g();l=d;d=D();....

여기서는 많은 변수를 초기화하기 위해 많은 메소드를 호출하고 있습니다. 각 초기화는 ,또는을 사용하고 ;있습니다. 이것은 다음과 같이 다시 작성할 수 있습니다.

r=v=>Math.random()*100|0;n=r(m=r(d=0));D=v=>A(n-x)+A(m-y);do{d=D(l=d,g());....

메소드가 전달 된 변수를 방해하지 않는다는 사실을 사용하고 그 사실을 사용하여 3 바이트를 면도하는 방법에 주목하십시오.

기타

.search 대신에 .indexOf

둘 다 동일한 결과를 제공하지만 search더 짧습니다. 검색에는 정규 표현식이 필요하지만 현명하게 사용하십시오.

`템플릿 문자열`

특정 조건에 따라 하나 이상의 스트링 부품을 연결해야 할 때 매우 유용합니다.

JS에서 quine을 출력하려면 다음 예제를 사용하십시오.

(f=x=>alert("(f="+f+")()"))()

vs.

(f=x=>alert(`(f=${f})()`))()

두 개의 큰 따옴표 (`) 안에있는 문자열 인 템플릿 문자열에서 a 안에있는 모든 것을 ${ }코드로 취급하고 결과 답변을 문자열에 삽입합니다.

나중에 몇 가지 요령을 게시하겠습니다. 행복한 골프!


답변

속성 속기 사용

속기 속성을 사용하면 변수를 배열 값으로 설정할 수 있습니다.

a=r[0];b=r[1] // ES5
[a,b]=r       // ES6 - 6 bytes saved

이것은 또한 다음과 같이 사용될 수 있습니다 :

a=r[0],b=r[2] // ES5
[a,,b]=r      // ES6 - 5 bytes saved

이것을 사용하여 변수를 뒤집을 수도 있습니다.

c=a,a=b,b=c // ES5 - uses extra variable
[b,a]=[a,b] // ES6 - not shorter, but more flexible

slice()기능을 사용하여 기능 을 단축 할 수도 있습니다 .

z = [1, 2, 3, 4, 5];

a=z.slice(1) // a = [2,3,4,5]; ES5
[,...a]=z    // a = [2,3,4,5]; ES6

기본 전환

ES6은 Base-2 (이진) 및 Base-8 (8 진수) 형식을 10 진수로 변환하는 훨씬 짧은 방법을 제공합니다.

0b111110111 // == 503
0o767       // == 503

+이진수, 8 진수 또는 16 진수 문자열을 10 진수로 변환하는 데 사용할 수 있습니다. 당신은 사용할 수 있습니다 0b, 0o그리고 0x각각 진수, 8 진수와 진수를 들면 :

parseInt(v,2) // ES5
+('0b'+v)     // ES6 - 4 bytes saved; use '0o' for octal and '0x' for hex
'0b'+v-0      // Shorter, but may not work in all cases
              // You can adapt this your case for better results

이> 7 번을 사용하는 경우 사용 parseInt하고 이름을 바꾸는 것이 더 짧 습니다.

(p=parseInt)(v,2)

이제에 p사용할 수있어 parseInt장기적으로 많은 바이트를 절약 할 수 있습니다 .


답변

함수와 함께 문자열 템플릿 사용

하나의 문자열을 인수로 사용하는 함수가있는 경우 ()식이없는 경우를 생략 할 수 있습니다 .

join`` // Works
join`foobar` // Works
join`${5}` // Doesn't work


답변

배열 이해 (Firefox 30-57)

참고 : 배열 이해는 표준화되지 않았으며 Firefox 58에서는 더 이상 사용되지 않습니다.


원래 ECMAScript 7 사양에는 여러 가지 새로운 배열 기반 기능이 포함되었습니다. 이들의 대부분이 확정 버전으로하지 않았지만, 파이어 폭스 지원 (ED)이 기능의 가능성이 가장 큰 : 대체 할 수있는 멋진 새 구문 .filter.mapfor(a of b)구문. 예를 들면 다음과 같습니다.

b.filter(a=>/\s/.test(a)).map(a=>a.length)
[for(a of b)if(/\s/.test(a))a.length]

보시다시피, 두 줄은 부피가 큰 키워드와 화살표 기능을 포함하지 않는 두 번째 줄 외에 다른 것이 아닙니다. 그러나 이것은 주문만을 설명한다 .filter().map(). .map().filter()대신에 어떻게됩니까 ? 실제로 상황에 따라 다릅니다.

b.map(a=>a[0]).filter(a=>a<'['&&a>'@')
[for(a of b)if(a<'['&&a>'@')a[0]]

b.map(a=>c.indexOf(a)).filter(a=>a>-1)
[for(a of b)if((d=c.indexOf(a))>-1)d]

b.map(a=>a.toString(2)).filter(a=>/01/.test(a))
[for(a of b)if(/01/.test(c=a.toString(2)))c]

또는 당신이 무엇을 원하는 경우 중 하나 .map 또는 .filter ? 글쎄, 그것은 일반적으로 덜 OK로 나타납니다.

b.map(a=>a.toString(2))
[for(a of b)a.toString(2)]

b.filter(a=>a%3&&a%5)
[for(a of b)if(a%3&&a%5)a]

따라서 제 충고는 일반적으로 .map and를 사용하는 곳마다 배열 이해를 사용하는 .filter것이지만 둘 중 하나만 사용하는 것이 아닙니다.

문자열 이해

ES7 이해에 대한 좋은 점은 .mapand와 같은 배열 별 함수와 달리 배열 뿐만 아니라 반복 가능한 객체 에서도.filter 사용할 수 있다는 것 입니다. 문자열을 다룰 때 특히 유용합니다. 예를 들어 문자열을 통해 각 문자를 실행하려면 다음을 수행하십시오 .cc.charCodeAt()

x=>[...x].map(c=>c.charCodeAt())
x=>[for(c of x)c.charCodeAt()]

그것은 상당히 작은 규모로 절약 된 2 바이트입니다. 문자열에서 특정 문자를 필터링하려면 어떻게해야합니까? 예를 들어, 이것은 대문자 만 유지합니다 :

x=>[...x].filter(c=>c<'['&&c>'@')
x=>[for(c of x)if(c<'['&&c>'@')c]

흠, 그것은 더 짧지 않습니다. 그러나 우리가 두 가지를 결합하면 :

x=>[...x].filter(c=>c<'['&&c>'@').map(c=>c.charCodeAt())
x=>[for(c of x)if(c<'['&&c>'@')c.charCodeAt()]

와우, 전체 10 바이트가 절약되었습니다!

문자열 이해의 또 다른 장점은 하드 코딩 된 문자열이 추가 바이트를 절약한다는 것입니다 of.

x=>[...'[](){}<>'].map(c=>x.split(c).length-1)
x=>[for(c of'[](){}<>')x.split(c).length-1]

x=>[...'[](){}<>'].filter(c=>x.split(c).length>3)
x=>[for(c of'[](){}<>')if(x.split(c).length>3)c]

인덱싱

배열 이해는 문자열 / 배열에서 현재 색인을 얻는 것이 조금 더 어려워 지지만 수행 할 수 있습니다.

a.map((x,i)=>x+i).filter ((x,i)=>~i%2)
[for(x of(i=0,a))if(++i%2)x+i-1]

주의해야 할 것은 조건이 충족 될 때뿐만 아니라 매번 인덱스가 증가 하도록하는 것입니다.

발전기 이해

생성기 이해는 기본적으로 배열 이해와 동일한 구문을 갖습니다. 괄호를 괄호로 바꾸십시오.

x=>(for(c of x)if(c<'['&&c>'@')c.charCodeAt())

이것은 배열과 거의 같은 방식으로 작동 하는 생성기 를 생성 하지만 다른 대답에 대한 이야기입니다.

요약

기본적으로 이해력은 일반적으로보다 짧지 만 .map().filter()상황의 세부 사항에 따라 결정됩니다. 두 가지 방법으로 시도하고 어느 것이 더 잘 작동하는지 확인하는 것이 가장 좋습니다.

추신 : 다른 이해 관련 팁이나이 답변을 향상시킬 수있는 방법을 제안하십시오!


답변

ES6의 함수 표현식은 화살표 표기법을 사용하며 ES5 버전과 비교할 때 바이트를 많이 절약하는 데 도움이됩니다.

f=function(x,y){return x+y}
f=(x,y)=>x+y

함수에 하나의 매개 변수 만있는 경우 괄호를 생략하여 2 바이트를 저장할 수 있습니다.

f=x=>x+1

함수에 매개 변수가 없다면 1 바이트를 저장하는 것처럼 선언하십시오.

f=()=>"something"
f=x=>"something"

주의 : 화살표 기능은 정확히 동일하지 않습니다 function () {}. 규칙 this이 다릅니다 (더 나은 IMO). 문서 보기


답변

eval여러 명령문과 함께 화살표 함수에 사용return

내가 우연히 발견 한 더 우스운 트릭 중 하나 …

여러 개의 문과을 필요로하는 간단한 화살표 함수를 상상해보십시오 return.

a=>{for(o="",i=0;i<a;i++)o+=i;return o}

에있는 a모든 정수를 반복 하는 단일 매개 변수를 허용하는 간단한 함수 [0, a)로, 출력 문자열의 끝 부분에 o이를 반환합니다. 예를 들어,이를 4매개 변수로 사용하여 호출하면 yield가 0123됩니다.

이 화살표 함수는 중괄호로 묶어야 하고 끝에 {}있어야합니다 return o.

이 첫 번째 시도의 무게는 39 바이트 입니다.

나쁘지는 않지만을 사용 eval하면이를 개선 할 수 있습니다.

a=>eval('for(o="",i=0;i<a;i++)o+=i;o')

이 함수는 코드를 래핑 eval하여 eval평가 에서 마지막 명령문을 작성 하여 중괄호와 return 문을 제거 했습니다 o. 이로 인해 evalreturn o이 리턴되고 o, 이제는 단일 명령문이므로 함수가 리턴 됩니다.

이 개선 된 시도의 무게는 38 바이트 이며 원래 바이트는 1 바이트입니다.

그러나 더 많은 것이 있습니다! 평가 문은 마지막 계산서에 평가 된 내용을 반환합니다. 이 경우로 o+=i평가 o되므로 ;o! (감사합니다, edc65!)

a=>eval('for(o="",i=0;i<a;i++)o+=i')

이 마지막 시도의 무게는 36 바이트에 불과 합니다. 원본보다 3 바이트가 절약되었습니다!

이 기술은 화살표 함수가 값을 반환하고 여러 명령문을 가질 필요가있는 일반적인 경우로 확장 될 수 있습니다 (다른 방법으로는 결합 할 수 없음)

b=>{statement1;statement2;return v}

된다

b=>eval('statement1;statement2;v')

바이트를 저장합니다.

statement2평가되면 다음 v과 같습니다.

b=>eval('statement1;statement2')

총 3 바이트를 절약합니다.