[javascript] arr = []가 arr = new Array보다 빠른 이유는 무엇입니까?

이 코드를 실행하고 아래 결과를 얻었습니다. 왜 []더 빠른지 궁금합니다 .

console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')

console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
  • 사용 []: 299ms
  • 사용 new: 363ms

Raynos 덕분 에이 코드 의 벤치 마크 와 변수를 정의하는 더 가능한 방법이 있습니다.

여기에 이미지 설명을 입력하십시오



답변

이전 답변에 대한 추가 확장 …

일반적인 컴파일러 관점에서 VM 별 최적화는 무시합니다.

먼저 코드를 토큰 화하는 어휘 분석 단계를 거칩니다.

예를 들어, 다음 토큰이 생성 될 수 있습니다.

[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)

더 많은 (또는 적은) 처리가 필요한지 이해할 수 있도록 충분한 시각화가 제공되기를 바랍니다.

  1. 위의 토큰을 기반으로 ARRAY_INIT가 항상 배열을 생성한다는 사실을 알고 있습니다. 따라서 단순히 배열을 만들어 채 웁니다. 애매 모호한 한 어휘 분석 단계에서는 ARRAY_INIT와 객체 속성 접근 자 (예 🙂 obj[foo]또는 문자열 / 정규 리터럴 (예 : “foo [] bar”또는 / [] /)과 괄호 를 이미 구분했습니다.

  2. 이것은 아주 작은 것이지만에 더 많은 토큰이 new Array있습니다. 게다가, 우리는 단순히 배열을 만들고 싶어한다는 것이 아직 명확하지 않습니다. 우리는 “새로운”토큰을 볼 수 있지만 “새로운”토큰은 무엇입니까? 우리는 새로운 “배열”을 원한다는 것을 나타내는 IDENTIFIER 토큰을 볼 수 있지만, JavaScript VM은 일반적으로 IDENTIFIER 토큰과 “네이티브 글로벌 객체”에 대한 토큰을 구별하지 않습니다. 따라서…

  3. IDENTIFIER 토큰이 발생할 때마다 스코프 체인을 찾아야합니다. Javascript VM에는 “인수”개체, 로컬로 정의 된 변수 등을 포함 할 수있는 각 실행 컨텍스트에 대한 “활성화 개체”가 포함되어 있습니다. 활성화 개체에서 찾을 수없는 경우 전역 범위에 도달 할 때까지 범위 체인을 찾기 시작합니다. . 아무것도 발견되지 않으면을 던집니다 ReferenceError.

  4. 변수 선언을 찾았 으면 생성자를 호출합니다. new Array암시 적 함수 호출이며 경험에 따르면 일반적으로 정적 C / C ++ 컴파일러가 “함수 인라이닝”을 허용하는 이유는 스파이더 몽키와 같은 JS JIT 엔진이 즉석에서 수행해야하는 이유입니다.

  5. Array생성자는 오버로드됩니다. Array 생성자는 기본 코드로 구현되므로 성능이 약간 향상되었지만 인수 길이를 확인하고 그에 따라 조치를 취해야합니다. 또한 하나의 인수 만 제공되는 경우 인수 유형을 추가로 확인해야합니다. new Array ( “foo”)는 [ “foo”]를 생성합니다. 여기서 new Array (1)은 [정의되지 않음]을 생성합니다

따라서 모든 것을 단순화하기 위해 : 배열 리터럴을 사용하면 VM은 배열이 필요하다는 것을 알고 있습니다. 과 new Array의 VM은 무엇을 알아 내기 위해 여분의 CPU 사이클을 사용할 필요가 new Array 실제로 않습니다.


답변

가능한 한 가지 이유는 new Array이름 조회 가 필요 Array하지만 (범위에 해당 이름의 변수가있을 수 있음) []그렇지 않습니다.


답변

좋은 질문. 첫 번째 예를 배열 리터럴이라고합니다. 많은 개발자들 사이에서 배열을 만드는 것이 선호되는 방법입니다. 리터럴이 직접 배열을 만드는 동안 새 Array () 호출의 인수를 확인한 다음 객체를 생성하면 성능 차이가 발생할 수 있습니다.

상대적으로 작은 성능 차이는이 점을 뒷받침합니다. 그런데 Object 및 object literal {}을 사용하여 동일한 테스트를 수행 할 수 있습니다.


답변

이것은 어떤 의미가 있습니다

객체 리터럴을 사용하면 많은 기능을 지원하는 코드를 작성할 수 있지만 코드 구현 자에게는 비교적 간단합니다. 생성자를 직접 호출하거나 함수 등에 전달 된 올바른 인수 순서를 유지할 필요가 없습니다.

http://www.dyn-web.com/tutorials/obj_lit.php


답변

또한 흥미로운 것은 배열길이를 미리 알고 있다면 (요소는 생성 직후에 추가 될 예정 임) 최근 Chrome 70+에서 지정된 길이배열 생성자를 사용하는 것이 훨씬 빠릅니다 .

  • 새 배열 ( % ARR_LENGTH % ) “– 100 % (빠름) !

  • [] “– 160-170 % (느리게)

측정 결과가 포함 된 차트.

테스트는 여기에서 찾을 수 있습니다-https: //jsperf.com/small-arr-init-with-known-length-brackets-vs-new-array/2

참고 :이 결과는 Chrome v.70 + 에서 테스트되었습니다 . 에서 파이어 폭스 V.70 IE 모두 거의 동일한 변형.


답변