소개
C와 같은 저수준 언어에는 malloc () 및 free ()와 같은 저수준 메모리 관리 프리미티브가 있습니다. 반면에 JavaScript의 메모리 프리미티브는 변수 (객체, 문자열 등)가 생성 된 다음 더 이상 사용하지 않을 때 "자동으로"제출 될 때 할당됩니다. 후자를 쓰레기 수집이라고합니다. 이 "자동"은 난로를 흡수하고 JavaScript (및 기타 고급 언어) 개발자에게 환상을 제공합니다. 메모리 관리를 무시할 수 있습니다.
메모리 수명주기
어떤 프로그래밍 언어에 관계없이 메모리 수명주기는 기본적으로 동일합니다.
1. 필요한 메모리를 할당하십시오
2. 사용 (읽기, 쓰기)
3. 릴리스 PS : "코끼리를 냉장고에 넣으십시오"
프로세스의 첫 번째 및 두 번째 부분은 모든 언어에서 명확합니다. 마지막 단계는 저수준 언어로는 명확하지만 JavaScript와 같은 고급 언어로 마지막 단계는 명확하지 않습니다.
JavaScript에 대한 메모리 할당
가변 초기화
할당 문제로 프로그래머를 방해하지 않기 위해 JavaScript는 변수를 정의 할 때 메모리 할당을 완료합니다.
코드 사본은 다음과 같습니다.
var n = 123; // 메모리를 숫자 변수에 할당합니다
var s = "azerty"; // 문자 유형을 제공합니다
var o = {
A : 1,
B : NULL
}; // 객체와 포함 된 변수에 대한 메모리를 할당합니다
var a = [1, null, "bra"]; // 배열에 대한 메모리 할당 및 포함 변수 (객체와 같은)
기능 f (a) {
A + 2를 반환합니다.
} // 함수에 대한 메모리 할당 (호출 가능한 개체)
// 함수 표현식은 객체를 할당 할 수도 있습니다
dodelement.addeventListener ( 'click', function () {
someElement.style.backgroundColor = 'Blue';
}, 거짓);
함수 호출을 통한 메모리 할당
일부 함수 호출은 객체 메모리를 할당합니다.
코드 사본은 다음과 같습니다.
var d = 새로운 날짜 ();
var e = document.createelement ( 'div'); // DOM 요소를 할당합니다
일부 방법은 새로운 변수 또는 새 개체를 할당합니다.
코드 사본은 다음과 같습니다.
var s = "azerty";
var s2 = s.substr (0, 3); // S2는 새로운 문자열입니다
// 문자열은 변하지 않기 때문에 JavaScript는 메모리를 할당하지 않을 수 있지만 0-3 범위 만 저장합니다.
var a = [ "ouais ouais", "nan nan"];
var a2 = [ "Generation", "Nan Nan"];
var a3 = a.concat (a2); // 새 배열에 배열 A와 배열 A2를 결합하는 네 가지 요소가 있습니다.
값의 사용
값을 사용하는 프로세스는 실제로 메모리 할당의 읽기 및 쓰기 작업이므로 변수 또는 객체의 속성 값을 작성하거나 함수의 매개 변수를 전달할 수 있음을 의미합니다.
메모리가 더 이상 필요하지 않을 때 해방됩니다
대부분의 메모리 관리 문제는이 단계에 있습니다. 여기서 가장 어려운 작업은 "할당 된 메모리가 실제로 필요하지 않다"는 것을 찾는 것입니다. 개발자는 종종 프로그램의 메모리가 더 이상 필요하지 않은 메모리를 결정하고 자유롭게 해제해야합니다.
고급 언어 통역사는 "가비지 수집기"가 포함되어 있으며 주요 작업은 메모리 할당 및 사용을 추적하여 할당 된 메모리가 더 이상 사용되지 않을 때 자동으로 해제 될 수 있도록하는 것입니다. 이 프로세스는 특정 메모리를 결정 해야하는지 여부를 결정하는 것이 불가능하기 때문에 근사치입니다 (일부 알고리즘으로 해결할 수 없음).
쓰레기 재활용
위에서 언급했듯이, 일부 메모리가 "필요하지 않은"지 여부를 자동으로 찾는 문제는 결정하기가 불가능합니다. 따라서 쓰레기 수집의 구현은 제한으로 일반적인 문제를 해결할 수 있습니다. 이 섹션에서는 주요 쓰레기 수집 알고리즘과 해당 한계를 이해하는 데 필요한 개념을 설명합니다.
인용하다
가비지 수집 알고리즘은 주로 참조 개념에 의존합니다. 메모리 관리 환경에서 객체에 다른 객체에 액세스 할 수있는 권한이있는 경우 (암시 적으로 또는 명시 적으로)이를 다른 객체를 참조하는 객체라고합니다. 예를 들어, JavaScript 객체는 프로토 타입 (암시 적 참조)에 대한 참조와 특성에 대한 참조 (명시 적 참조)를 갖습니다.
여기에서 "객체"의 개념은 특수 JavaScript 객체뿐만 아니라 기능 범위 (또는 글로벌 어휘 스코프)의 개념입니다.
참조 수 쓰레기 수집
이것은 가장 쉬운 쓰레기 수집 알고리즘입니다. 이 알고리즘은 "객체에 다른 객체가 참조되는지 여부"로 "객체가 더 이상 필요하지 않은지"를 단순화합니다. 객체에 대한 기준이 없으면 (제로 참조), 객체는 쓰레기 수집 메커니즘에 의해 재활용됩니다.
예를 들어
코드 사본은 다음과 같습니다.
var o = {
A : {
B : 2
}
};
// 두 객체가 만들어지고, 하나는 다른 객체가 다른 속성으로 참조되고, 다른 객체는 변수에 할당됩니다.
// 분명히, 그들 중 누구도 쓰레기로 수집 할 수 없습니다.
var o2 = O; // O2 변수는 "이 개체"에 대한 두 번째 참조입니다.
o = 1; // 이제 "이 개체"의 원래 참조 O는 O2로 대체됩니다.
var oa = o2.a; // "이 개체"의 속성을 참조하십시오.
// 이제 "이 개체"에 대한 두 가지 참조가 있습니다. 하나는 O2이고 다른 하나는 OA입니다.
O2 = "Yo"; // 원래 객체는 이제 제로 참조입니다
// 그는 재활용 할 수 있습니다
// 그러나 속성 A의 대상은 여전히 OA에 의해 참조되므로 아직 재활용 할 수 없습니다.
OA = NULL; // 속성이있는 개체는 이제 0으로 참조됩니다.
// 쓰레기를 수집 할 수 있습니다
제한 : 재활용 참조
이 간단한 알고리즘은 객체가 다른 객체를 참조하면 (원형 참조를 형성) "더 이상 필요하지 않을 수 있지만"재활용되지 않는다는 제한이 있습니다.
코드 사본은 다음과 같습니다.
함수 f () {
var o = {};
var o2 = {};
OA = O2; // o 참조 o2
o2.a = O; // o2 따옴표 o
"Azerty"를 반환합니다.
}
에프();
// 두 객체가 생성되고 서로를 참조하여 루프를 형성합니다.
// 호출 후 함수의 범위를 남기지 않습니다.
// 따라서 쓸모없고 재활용 할 수 있습니다
// 그러나 참조 카운팅 알고리즘은 최소한 한 번은 서로 참조를 가지고 있으므로 재활용되지 않습니다.
실제 사례
IE 6, 7 DOM 객체에 대한 참조 계산의 재활용. 그들에게 일반적인 문제는 메모리 누출입니다.
코드 사본은 다음과 같습니다.
var div = document.createelement ( "div");
div.onclick = function () {
dosomething ();
};
// div는 이벤트 처리 속성을 가리키는 참조가 있습니다.
// 이벤트 처리는 기능 범위에서 액세스 할 수있는 DIV에 대한 참조도 있습니다.
//이 원형 기준은 두 개체가 수집 된 쓰레기로 만듭니다.
마크 클리어링 알고리즘
이 알고리즘은 "객체가 더 이상 필요하지 않은지"를 "객체를 사용할 수 있는지 여부"로 단순화합니다.
이 알고리즘은 루트 (javaScript에서 루트는 글로벌 오브젝트)라는 객체를 설정한다고 가정합니다. 정기적으로, 쓰레기 수집기는 루트에서 시작하여 루트에서 참조 된 모든 물체를 찾은 다음이 객체에서 참조 된 물체를 찾습니다 ... 루트에서 시작하여, 쓰레기 수집기는 얻을 수있는 모든 객체와 얻을 수없는 모든 물체를 찾습니다.
이 알고리즘은 이전의 알고리즘보다 낫습니다. "제로 참조가있는 객체"는 항상 사용할 수 없기 때문에, 반드시 사실은 아니며, "원형 참조"를 참조하십시오.
2012 년부터 모든 현대식 브라우저는 TAG-Clean Garbage Collection 알고리즘을 사용했습니다. JavaScript Garbage Collection 알고리즘의 모든 개선은 태그 청소 알고리즘 자체를 개선하지 않고도 태그 청소 알고리즘의 개선과 더 이상 객체가 필요하지 않은지에 대한 단순화 된 정의를 기반으로합니다.
원형 참조는 더 이상 문제가되지 않습니다
위의 예에서, 함수 호출이 반환 된 후, 두 객체는 글로벌 오브젝트에서 검색 할 수 없습니다. 따라서 그들은 쓰레기 수집가에 의해 재활용 될 것입니다.
두 번째 예는 또한 DIV와 이벤트 처리를 루트에서 검색 할 수 없으면 쓰레기 수집기에 의해 재활용됩니다.
제한 : 객체를 명시 적으로 사용할 수 없어야합니다
이것은 제한이지만, 거의 깨지지 않기 때문에 실제로는 쓰레기 수집 메커니즘에 관심이있는 사람은 거의 없습니다.