2013-08-09 3 views
6

기존의 작업 코드베이스를 JavaScript를 사용하여 객체 지향으로 만들려고합니다. 내 시스템은 그룹 인을 포함하는 JSON을 일대 다 관계로으로 가져 와서이를 페이지에서 시각화합니다. 항목을 다른 그룹으로 이동할 수 있으며 해당 그룹 내의 위치를 ​​계산해야합니다. 따라서 주변의 단체 및 티켓을 모두 알고있는 이벤트를 수립해야합니다.JavaScript 클래스와 jQuery 객체 사이의 순환 종속성

저는 John Resig's 간단한 자바 스크립트 상속 설정을 사용하여 ItemGroup의 두 클래스를 설정하고 있습니다. 각각의 Item이 인스턴스화되면 부모에게 Group이라는 것을 다시 참조합니다. 내 문제 내가 내 이벤트를 설정하고자 할 때 발생하고, 가장 쉽게 다음과 같은 기능에 의해 설명 :

var Group = Class.extend({ 
    ... 
    // Calculate where to place the new item within the group 
    calculate_new_position: function(item) { 
    var pos = -1; 
    // Loop through all DOM items in groups body 
    $(".item", this.elBody).each(function(i) { 

     // Retrieve it's class object 
     var next = $(this).data("_obj"); 

     // Calculating things using the class reference 
     var lowerPrio = item.tData.priority < next.tData.priority, 
      lowerId = item.id < next.id; 

     if(lowerPrio || lowerId) { 
     pos = i; 
     return false; 
     } 
    }); 
    return pos; 
    }, 
    ... 
)}; 

참고 위의 코드에서 .data("_obj")의 사용. 기본적으로 항목 정렬과 같은 작업을 수행해야하는 경우 그룹의 모든 항목의 DOM (보기/컨트롤러)에 해당하는 개체 (모델)를 알아야합니다. 이제 Group 클래스를 만들면 각 Item을 만들 때 내 Group (예 : Group.items = [i1, i2...]) 내에서 참조를 추가 한 다음 DOM 요소를 반복하지 않고 Item 인스턴스를 반복 할 수 있습니다. 그러나 내가 같은(GroupItem에 대해 알지 못해서) Item을 다른 Group으로 옮기고 싶을 때와 같이 비슷한 문제가 생길 것이라고 생각합니다.

짧은 이야기 : 본질적으로 위험한/순진/무의미한 클래스가 인스턴스화 될 때 DOM 요소가 만들어지고 다시 클래스를 가리키는 것입니까? 이것은 원형 종속성과 재귀적인 악몽 같은 느낌이지만 객체에 대한 참조는 그리 끔찍한 것이 아닙니다. 만약 내가 다른 것을하고 있다면 은 정말로 어리 석고 훨씬 간단한 방법이있다.

+0

Backbone.js가 어떻게 사용했는지 살펴 보셨습니까? 'view' 객체는'model' (Item, Group 클래스)과 DOM 엘레멘트'el'에 대한 참조를 가지고 있습니다. 그것을하기위한 여러 가지 방법과 백본이 있습니다.js는 여기에 어떤 방법도 추천하지 않습니다 : http://backbonejs.org/#FAQ-tim-toady – vsr

답변

2

모든 최신 브라우저 가비지 수집기는 순환 참조를 처리 할 수 ​​있습니다. 개체에 대한 모든 참조를 잃어 버리고 DOM에서 모든 HTML 노드를 제거하는 경우 브라우저에서 개체 참조를 확인하고 가비지 수집을 방지하는 등의 방식으로 개체를 가비지 수집합니다. 이벤트 핸들러에주의하십시오. 제거하지 않으면 리퍼런스를 유지할 수 있습니다.

이전 버전의 IE에서 순환 참조에 문제가 있다고 들었습니다. 그 대답에서 Precise explanation of JavaScript <-> DOM circular reference issue

: depht 설명에 대한 자세한 내용 IE의 이전 버전은 DOM 요소에 추가 된 원형 처리하지 않은 특성을 가진 특정 문제를했기 때문에 jQuery의 .DATA() 일을 더 신뢰할 수 해당 속성의 데이터를 적절하게 참조하므로 참조가 있어야 할 때 물건을 누락시키지 않습니다 (유출). .data()는 안전하고 누출되지 않는 문자열 인 DOM 요소에서 하나의 추가 된 속성 만 사용하여이를 해결합니다. 이 문자열은 DOM 요소와 연결하려는 모든 속성을 포함 할 수있는 자바 스크립트 객체의 키입니다. 이러한 속성은 모두 브라우저에서 순환 참조 버그가없는 일반 자바 스크립트에 저장되므로이 방법을 사용하면 누출이 발생하지 않습니다.

D3.js를보고 싶을 수도 있습니다.DOM 요소에 데이터를 바인딩하고 시각화를 생성하는 쉬운 방법을 제공합니다. http://d3js.org/

D3을 사용하면 숫자 배열을 원형 SVG 태그의 배열에 바인딩하고 각 원이 번호에 따라 반경을 갖도록 할 수 있습니다 관련 지을 수 있었던 배열의

편집 : $ .remove()를 사용하면 이벤트 처리기도 제거된다는 사실을 잊어 버렸습니다. 그러나 예를 들어 (제거 된) HTML 노드에 대한 참조가있는 클로저 내부의 이벤트 핸들러가있는 경우 가비지 수집되지 않습니다. 이것은 대개 큰 문제는 아닙니다. 일단 DOM 외부에 있으면 리소스가 너무 많이 소모되지 않으므로 반복적으로 클로저 참조를 아는 한 스택 할 수 없기 때문입니다.

1

jQuery.data을 사용하면 dom 요소에 아무런 영향을주지 않습니다. dom 요소는 *에 관계없이 기본 키 항목을 jQuery 내부 캐시에 저장합니다. 만약 따라서 생성 한 참조 JS에서 JS하는 것이다

var div = document.createElement("div"); 
$(div).data("asd", "daa") 
console.log(div[jQuery.expando]); 
//41 
console.log(jQuery.cache[41].data.asd); 
//"daa" 

(분명 상기 jQuery를 내부이며 생산 코드에 의존하지 않아야) 데이터가있는 경우 누출, 상기

당신은 jQuery를 통해 모든 조작을 수행하지 않습니다. 왜냐하면 jQuery가 그 뒤를 따라 간다면 알림을받지 않기 때문입니다.

위젯 클래스를 사용하는 가장 좋은 방법은 담당하는 모든 요소를 ​​제거하고 연결된 모든 이벤트의 바인딩을 해제하고 모든 DOM 참조를 null로 설정하는 방법을 제공하는 것입니다.

* 요소에 대한 이벤트 나 데이터가 전혀없는 경우 엔트리가 존재하지 않습니다. 그러나 어떤 이유로 엔트리가 존재한다면, jQuery.data를 사용하는 것은 그 요소 자체와 상호 작용하지 않을 것이다.

1

@ 호프만의 대답은 설명과 함께 실용적인 조언을 제공하기 때문에 좋습니다. Backbone.js의 작동 방식에 영감을받은 다른 관점을 제시합니다. 이것은 초기 주석에서 @vsr이 제안한 것을 확장 한 것입니다.

기본 추력 : JS 개체를 $ .data()에 저장하지 마십시오.

$ .data()를 사용하면 $ (foo)를 사용하여 DOM 객체를 검색 한 다음 해당 속성으로 드릴 다운하여 사용자 정의 JS 함수로 이동하여 더 많은 DOM 요소를 조작하여 사용자 정의 함수. 이것은 지나치게 복잡하고 비효율적입니다.

더 나은 방법은 필요에 맞는 구문과 메커니즘을 사용하여 "순수 JS"개체 집합을 만드는 것입니다. 그런 다음이 객체는 필요할 때만 DOM 요소를 가리키는 속성을 가질 수 있습니다. Backbone (다시)은 jQuery에서 선택한 DOM 요소도 캐시하는 것이 좋습니다. 이러한 "순수 JS"객체를 처리하는 것은 $ .data()를 사용하는 것보다 유지 보수가 더 빠르고 쉽습니다. 또한 JS와 HTML 사이의 추상화가 증가합니다. 이는 좋은 것입니다.

또한 일대일 관계 만있는 경우에도 개체를 중첩하지 않는 것이 좋습니다. "그룹"의 "항목"속성을 만들지 마십시오. 대신, 그룹과 항목 모두의 배열을 유지하고 하나 (또는 ​​둘 다)가 회원이 아닌 참조로 연관을 관리하게하십시오.