javascript - 해제 - 자바스크립트 배열 선언




JavaScript 배열은 실제 메모리에서 어떻게 표현됩니까? (2)

여기에 생각을위한 음식이 있습니다. jsperf를 사용하여 일부 JavaScript 엔진이 구현 하는 간단한 배열 최적화를 테스트했습니다 .

테스트 케이스는 백만 개의 엘리먼트로 구성된 두 개의 배열을 생성합니다. 배열에는 숫자 만 포함됩니다. b 배열에는 객체 인 첫 번째 요소를 제외하고 같은 번호가 포함됩니다.

var a = [ 0 ], b = [ { valueOf: function() { return 0; } } ];
for( var i = 1;  i < 1000000;  ++i ) {
    a[i] = b[i] = i;
}

b 배열의 첫 번째 요소에있는 개체의 valueOf 속성은 0 반환하므로 산술은 첫 번째 배열과 동일합니다.

그런 다음 두 테스트는 두 배열의 모든 값을 단순히 합산합니다.

빠른 배열 :

var x = 0;
for( var i = 0;  i < 1000000;  ++i ) {
    x += a[i];
}

느린 배열 :

var x = 0;
for( var i = 0;  i < 1000000;  ++i ) {
    x += b[i];
}

jsperf의 테스트 결과에서 볼 수 있듯이 Chrome에서 숫자 배열은 약 5 배 빠르며 Firefox에서는 숫자 배열이 약 10 배 빨라지고 IE에서는 약 2 배 빠릅니다.

이것은 배열에 사용 된 내부 구조를 직접적으로 드러내지는 않지만이 두 가지가 서로 상당히 다르다는 것을 알 수 있습니다.

JavaScript 배열에 혼합 된 데이터를 저장하고 배열의 요소를 다른 유형으로 변경할 수 있다는 것을 이해합니다. 통역사는 어떤 요소가 물리적 메모리의 어떤 위치에 있는지 어떻게 추적합니까? 또한 요소를 더 큰 데이터 유형으로 변경하면 다음 요소의 데이터 덮어 쓰기를 방지 할 수 있습니다.

배열은 실제 객체에 대한 참조 만 저장한다고 가정하고 배열에 배치 될 때 원시 객체는 장면 뒤에 래핑됩니다.

이 경우를 가정하면, 내가 원시 변수에 다른 핸들을 가지고 배열에 저장된 값이 동시성을 유지합니까?

나는 아마 이미 내 자신의 질문에 대답했지만, 나는 확실히 모른다. 그리고 나는 그 문제에 대한 어떤 정보도 찾을 수 없다.


일반적으로 배열은 고정 길이의 메모리 연속 블록을 할당합니다. 그러나 Javascript에서 배열은 특수 생성자 및 접근 자 메서드가있는 Object 유형입니다.

어떤 뜻인가요?

var arr = new Array(100000);

메모리를 할당하지 않습니다! 사실, 단순히 배열의 length 속성 값을 설정합니다. 배열을 만들 때 크기가 자동으로 커지면 선언 할 필요가 없습니다. 따라서 다음과 같이 사용해야합니다.

var arr = [];

Javascript의 배열은 스파 스입니다. 즉, 배열의 모든 요소에 데이터가 포함될 수있는 것은 아닙니다. 즉, 실제로 데이터가 포함 된 요소 만 배열에 존재합니다. 이렇게하면 어레이에서 사용하는 메모리 양이 줄어 듭니다. 값은 키가 아닌 오프셋으로 나타납니다. 그것들은 단순히 편리함의 방법 일 뿐이며 복잡한 수치 해석에 사용되지 않습니다.

Javascript의 배열은 입력되지 않으므로 요소의 값은 객체, 문자열, 숫자, 부울, 함수 또는 배열이 될 수 있습니다. 배열과 객체의 가장 큰 차이점은 배열의 가장 큰 정수 키보다 큰 값을 갖는 길이 속성입니다.

예 :

빈 배열을 만들고 인덱스 0과 인덱스 99에 두 개의 요소를 추가 할 수 있습니다. 길이는 100이지만 배열의 요소 수는 2가됩니다.

var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]

직접 질문에 답변하려면 다음을 수행하십시오.

Q. JavaScript 배열에 혼합 된 데이터를 저장하고 배열의 요소를 다른 유형으로 변경할 수 있다는 것을 이해합니다. 통역사는 어떤 요소가 실제 메모리의 어느 위치에 있는지 어떻게 추적합니까? 또한 요소를 더 큰 데이터 형식으로 변경하면 다음 요소의 데이터 덮어 쓰기가 어떻게 방지됩니까?

A. 위의 내 의견을 읽은 적이 있다면 지금 쯤은 이미 알고있을 것입니다. Javascript에서 배열은 Hashtable Object 유형이므로 인터프리터는 실제 메모리를 추적 할 필요가 없으며 요소의 값을 변경하면 인접한 메모리 블록에 저장되지 않으므로 다른 요소에 영향을 미치지 않습니다.

-

Q. 배열은 실제 객체에 대한 참조 만 저장한다고 가정하고 배열에 배치 될 때 프리미티브는 장면 뒤에 래핑됩니다. 이 경우, 원시 변수에 다른 핸들이 있고 배열에 저장된 값이 동시성을 유지한다면?

A. 아니요, 프리미티브는 랩핑되지 않습니다. 배열에 할당 된 프리미티브를 변경해도 배열에있는 값은 값에 따라 변경되지 않습니다. 반면에 객체는 참조로 저장되므로 객체 값을 변경하면 해당 배열의 변경 사항이 반영됩니다.

다음은 시도 할 수있는 예입니다.

var arr = [];
var obj = { name: "John" };
var isBool = true;

arr.push(obj);
arr[1] = isBool;

console.log(arr[0]); // print obj.name
console.log(arr[1]); // print true

obj.age = 40;        // add age to obj
isBool = false;      // change value for isBool

console.log(arr[0]); // value here will contain age
console.log(arr[1]); // value here will still be true

또한 다음 두 가지 방법으로 배열을 초기화 할 때 다른 동작을합니다.

var arr = new Array(100);
console.log(arr.length);        // prints 100
console.log(arr);               // prints []

var arr2 = new Array(100, 200);
console.log(arr2.length);       // prints 2
console.log(arr2);              // prints [100, 200]

Javascript 배열을 연속적인 메모리 블록으로 사용하려면 TypedArray 를 사용해야합니다. TypedArray를 사용하면 한 블록의 메모리를 바이트 배열로 할당하고 원시 이진 데이터에보다 효율적으로 액세스 할 수 있습니다.

Javascript의 복잡한 점에 대해 ECMA-262 스펙 (ver 5.1) 을 읽으면 자세히 알 수 있습니다.





weakly-typed