자바 스크립트에서 "약한 참조"를 만들 수 있습니까?


97

자바 스크립트에서 다른 개체에 대한 "약한 참조"를 만드는 방법이 있습니까? 다음은 약한 참조가 무엇인지 설명하는 위키 페이지입니다. 다음은 Java로 설명하는 또 다른 기사입니다. 누구든지 자바 스크립트 에서이 동작을 구현하는 방법을 생각할 수 있습니까?


4
ES6에 대한 약한 참조가 논의되고 있습니다. 눈을 떼지 마십시오.
Ryan Smith

2
에서 * 공식 스펙 위키 / 토론 wiki.ecmascript.org/doku.php?id=strawman:weak_refs , 현재 "최근 수정 된 항목 : 2013년 2월 2일 22시 25분"에서 * 다른 사양 토론 esdiscuss.org/topic/what -is-the-status-of-weak-references , 현재 마지막 게시물 "Sun Mar 3 11:56:05 PST 2013"
Destiny Architect

대부분의 경우 WR은 여기에서 설명 하는 Lapsed Listener 문제 를 해결하기위한 시도입니다 . [ stackoverflow.com/questions/43758217/… . 그 질문에 좋은 대답이 있었다면 WR이 많이 필요하지 않을 것이라고 생각합니다.
James

@supercat 내가 지나친 청취자 질문 에 대한 답변을 게시했습니다 .
James

답변:


39

JavaScript에서 weakref에 대한 언어 지원이 없습니다. 수동 참조 계산을 사용하여 직접 롤링 할 수 있지만 특히 매끄럽지는 않습니다. 프록시 래퍼 개체를 만들 수 없습니다. JavaScript 개체에서는 가비지 수집 시점을 알 수 없기 때문입니다.

따라서 'weak reference'는 add-reference 및 remove-reference 메소드를 사용하여 간단한 조회에서 키 (예 : 정수)가되며, 더 이상 수동으로 추적되는 참조가 없으면 항목을 삭제하여 향후 조회를 계속 사용할 수 있습니다. null을 반환하는 키입니다.

이것은 실제로 weakref는 아니지만 동일한 문제 중 일부를 해결할 수 있습니다. 일반적으로 복잡한 웹 애플리케이션에서 DOM 노드 또는 이벤트 핸들러와 이와 관련된 객체 (예 : 클로저) 사이에 참조 루프가있을 때 브라우저 (일반적으로 IE, 특히 이전 버전)에서 메모리 누출을 방지하기 위해 수행됩니다. 이러한 경우 전체 참조 계수 체계가 필요하지 않을 수도 있습니다.


2
코드를주의 깊게 조사 (또는 사용)하지는 않았지만 es-lab에는 기본 WeakMap 에뮬레이션을 제공하는 스크립트가 있습니다. Aurora 6 (Mozilla)에는 비표준 WeakMap 구현이 있습니다.
theazureshadow

2
ES6에서는이 답변이 더 이상 정확하지 않습니다. 내 대답은 아래를 참조 stackoverflow.com/a/28567560/745190
thelastshadow

9
ES6 WeakMaps는 진정한 약한 참조가 아니기 때문에 여전히 정확합니다. WeakMaps는 객체를 키로 만 받아들이고 이러한 객체에 대한 참조는 약하게 유지됩니다. 참조 stackoverflow.com/questions/32397729/...
CodeManX

약한지도를 에뮬레이트하는 클래스를 작성하고 여기에 게시했습니다. stackoverflow.com/a/47017206/491553
Ryan Shillington


11

업데이트 : 2019 년 9 월

아직 약한 참조를 사용하는 것은 불가능하지만 JavaScript의 WeakRef 가 Work In Progress 이기 때문에 곧 가능할 것 입니다. 아래 세부 정보.

신청

현재 단계 3의 제안 은 완전한 사양을 가지고 있으며 추가 개선에는 구현 및 사용자의 피드백이 필요함 을 의미 합니다.

WeakRef의 제안은 기능의 두 가지 주요 새로운 조각을 포함한다 :

  • WeakRef 클래스를 사용하여 개체에 대한 약한 참조 만들기
  • FinalizationGroup 클래스를 사용하여 개체가 가비지 수집 된 후 사용자 정의 종료 자를 실행합니다.

사용 사례

약한 참조 의 주된 용도 는 큰 개체를 포함하는 캐시 또는 매핑을 구현하는 것입니다. 여기서 큰 개체는 캐시 또는 매핑에 표시되기 때문에 단독으로 유지되지 않는 것이 좋습니다.

마무리 는 프로그램 실행에 도달 할 수 없게 된 개체 이후에 정리할 코드를 실행하는 것입니다. 사용자 정의 종료자는 몇 가지 새로운 사용 사례를 가능하게하며 가비지 수집기가 알지 못하는 리소스를 관리 할 때 메모리 누수를 방지하는 데 도움이 될 수 있습니다.

출처 및 추가 자료

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references


1
Firefox Nightly는 WeakRef에 대한 실험적 지원을 추가했습니다. 다음은 WeakSet의 반복 가능한 버전을 만드는 데 사용하는 구현의 예입니다. gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley

3

진정한 약한 참조, 아니요, 아직은 아닙니다 (그러나 브라우저 제작자는 주제를보고 있습니다). 그러나 약한 참조를 시뮬레이션하는 방법에 대한 아이디어가 있습니다.

개체를 구동하는 캐시를 만들 수 있습니다. 객체가 저장 될 때 캐시는 객체가 차지할 메모리 양을 예측합니다. 이미지 저장과 같은 일부 항목의 경우 이것은 간단합니다. 다른 사람들에게는 이것이 더 어려울 것입니다.

객체가 필요할 때 캐시에 요청합니다. 캐시에 객체가 있으면 반환됩니다. 없으면 항목이 생성되고 저장되고 반환됩니다.

약한 참조는 예측 된 총 메모리 양이 특정 수준에 도달하면 항목을 제거하는 캐시에 의해 시뮬레이션됩니다. 검색 빈도에 따라 가장 적게 사용되는 항목을 예측하고, 가져온 시간에 따라 가중치를 부여합니다. 항목을 생성하는 코드가 클로저로 캐시에 전달되는 경우 '계산'비용도 추가 될 수 있습니다. 이렇게하면 캐시가 구축하거나 생성하는 데 매우 비싼 항목을 보관할 수 있습니다.

삭제 알고리즘이 핵심입니다.이 오류가 발생하면 가장 인기있는 항목을 제거 할 수 있기 때문입니다. 이것은 끔찍한 성능을 유발합니다.

캐시가 저장된 객체에 대한 영구 참조 가있는 유일한 객체 한, 위의 시스템은 진정한 약한 참조의 대안으로 잘 작동합니다.


25
당신이 말한 대부분이 약점과 무관하지 않습니까?
Erik Kaplun 2011

22
@ JL235-약한 참조의 중요한 용도는 캐시가 아니라 이벤트 처리기입니다. 존재하는 동안 다른 이벤트를 관찰해야하는 객체가 있지만 GC의 목적을위한 참조를 구성하기 위해 알림 목록에 있다는 사실을 원하지 않습니다.
Malvolio

7
약한 참조는 캐싱과 관련이 없습니다. 약한 참조는 무언가를 추적하고 싶지만 추적중인 개체에 대한 나머지 참조가없는 경우 삭제할 수 있음을 의미합니다.
fabspro 2013 년

8
자동 만료를 위해 약한 참조를 사용하여 캐시를 구축하는 사용 사례가 분명히 있습니다.
Phil Freeman

5
캐싱은 전통적으로 약한 참조의 가장 큰 이유입니다. 이벤트 처리기 DOM 문제는 IE 탐색기 버그가 있습니다.
axkibe


2

JL235위에서 제안한 것처럼 캐싱 메커니즘을 사용하여 약한 참조를 에뮬레이트하는 것이 합리적입니다. 약한 참조가 기본적으로 존재하는 경우 다음과 같은 동작을 관찰합니다.

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

캐시를 사용하면 다음을 관찰 할 수 있습니다.

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

참조 보유자로서 값을 참조 할 때 어떤 가정도해서는 안됩니다. 이는 캐시를 사용하는 것과 다르지 않습니다.



-4

EcmaScript 6 (ES Harmony)에는 WeakMap 객체가 있습니다. 최신 브라우저 간의 브라우저 지원은 꽤 좋습니다 (Firefox의 마지막 3 개 버전, Chrome 및 곧 출시 될 IE 버전에서도 지원됨).


29
이것은 정확히 동일하지 않습니다. A는 WeakMap약세가없는 objects--에 대한 참조 제공하지 않습니다 WeakMap에 약한 참조,하지만 키를 . 약한 참조가 맵에 존재한다는 사실은 메모리 누수 방지 메커니즘 일 뿐이며 그렇지 않으면 사용자가 관찰 할 수 없습니다.
EyasSH

1
가치가 아니라 약한 열쇠라는 것이 맞습니다. 그러나 약한 참조를 사용하는 모든 목적은 참조 된 개체의 가비지 수집을 허용하는 것입니다. OP는 두 개의 링크를 게시했는데, 두 번째 링크는 확장 할 수없는 객체에 ID를 추가하는 것이며, 실제로 JavaScript의 WeakMap에 해당하는 Java 인 WeakHashMap 사용을 권장합니다.
thelastshadow

12
이후 약한 참조 구현 WeakMap를 사용하여 행운 weakmap.get(new String('any possible key that has ever existed or ever will exist'))것입니다 항상 일을 undefined. 유용 하지 않습니다 . 반대 투표!
user3338098

-5

http://www.jibbering.com/faq/faq_notes/closures.html

ECMAScript는 자동 가비지 수집을 사용합니다. 사양은 세부 사항을 정의하지 않으므로 구현자가 정렬하도록 남겨두고 일부 구현은 가비지 수집 작업에 매우 낮은 우선 순위를 부여하는 것으로 알려져 있습니다. 그러나 일반적인 아이디어는 객체가 참조 할 수 없게되면 (그 객체에 대한 나머지 참조가 실행 코드에 액세스 할 수있게함으로써) 가비지 수집에 사용할 수있게되며 향후 어느 시점에서 소멸되고 소비되는 모든 리소스가 해제되고 반환된다는 것입니다. 재사용을 위해 시스템에.

이것은 일반적으로 실행 컨텍스트를 종료 할 때 발생합니다. 범위 체인 구조, Activation / Variable 개체 및 함수 개체를 포함하여 실행 컨텍스트 내에서 생성 된 모든 개체는 더 이상 액세스 할 수 없으므로 가비지 수집에 사용할 수있게됩니다.

더 이상 사용할 수 없게되는 약한 사람은 없습니다.


10
참조주기를 피하는 것이 약한 참조를 사용하는 유일한 이유는 아닙니다. 객체 인스턴스 풀링 / 캐싱 등에 매우 편리합니다.
푹신한 '

WeakReference의 정의는 문제가 아닙니다. 또한 위의 의견에 동의합니다.
Yuri Yaryshev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.