2016-08-06 1 views
-1

javascript 프로토 타입 상속을 사용하여 DOM 요소에서 CSS 속성을 수집하는 다음 스 니펫을 고려하십시오. elem 배열은 DOM 노드에 해당하는 객체를 포함하고 각 객체는 style 필드를 가지며 각 elem[x].style도 객체입니다. 그리고 elem[x].style 오브젝트는 __proto__을 통해 연결된 DOM 트리 계층 구조를 반복합니다. rootStyle 변수는 모든 elem[x].style 프로토 타입 체인의 루트 역할 :브라우저에서 javascript __proto__를 자연스럽게 구현 된 알고리즘의 일부로 사용

var rootStyle = {}, 
    elem = [{}, {}, {}]; 

rootStyle.__proto__ = null; 
rootStyle.fontSize = '14px'; 

elem[0].style = {}; 
elem[0].style.__proto__ = rootStyle; 
elem[0].style.fontWeight = 'bold'; 
elem[0].className = 'my-elem-123'; 

elem[1].style = {}; 
elem[1].style.__proto__ = rootStyle; 
elem[1].style.fontStyle = 'italic'; 
elem[1].className = 'my-elem-456'; 

elem[2].style = {}; 
elem[2].style.__proto__ = elem[1].style; 
elem[2].style.textDecoration = 'underline'; 
elem[2].className = 'my-elem-789'; 
... 
// later in the code 
var cssCode = [], 
    i, len = 3; 
for(i = 0; i < len; i++) { 
    cssCode.push('.' + elem[i].className + '{' + getCssRules(elem[i]) + '}'; 
} 

function getCssRules(elem) { 
    var result = [], 
     cssProperty, cssValue; 
    for(cssProperty in elem.style) { 
     // No hasOwnProperty check! 
     // Here (and in for..in loop) happens the lookup magic that I need 
     cssValue = elem.style[cssProperty]; 
     result.push(cssValue + ':' + cssProperty + ';'; 
    } 
    return result; 
} 

하고 여기 말했다 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto, 나는 때문에 성능에 미치는 영향의 객체의 프로토 타입을 변경하지 마십시오.

개체 키 - 값 조회는 내부적으로 많은 작업으로 바뀌지 만 어쨌든 관리되는 언어 일 수 있으며 여기의 모든 작업에는 오버 헤드가 있습니다. 그리고 미친 깊이의 프로토 타입 체인을 만들지 않으면 프로토 타입 체인 조회의 속도가 "단일 단계"작업의 속도와 비슷해야합니다. 즉 O (1)의 복잡성에 가깝습니다. 그리고 내 algorythm 자연스럽게 그런 행동으로 데이터 구조가 자연스럽게 필요한 경우 엉덩이에 고통 - 내 자신의 체인 조회 또는 일부 완전히 다른 솔루션을 구현하는 "단지 __proto__ 나쁜"때문입니다.

그렇다면 __proto__의 경우 또는 좋거나 나쁜 용도는 무엇입니까?

이 같은 elem 배열에 실제 DOM 노드에 대한 참조를 저장하는 경우 무슨 일이 일어날 지

:

elem[0].domNode = document.body.childNodes[0]; 
elem[1].domNode = document.body.childNodes[1]; 
elem[2].domNode = elem[1].domNode.childNodes[0]; 

나쁜, 좋은 아니면, 중요하지 않습니다 사용자 정의 프로토 타입 체인에 객체를 연결하고, 개체 일반적인 프로토 타입 체인, 여기서 엔진의 최적화가 실패합니까?

: 이제 알았습니다. __proto__ 설정과 관련된 모든 혼란은 정확하게 __proto__ 참조를 변경하는 것입니다. 그것은 나쁜 것을 유발합니다 (첫번째 코멘트의 링크를보십시오). 우리는 받아 들여진 응답의 구문을 고수해야합니다. 첫째로 나는 나쁜 것들이 빈 프로토 타입 자체 때문에 발생한다고 생각했다. 최적화를 위해 자바 스크립트 엔진에 필요한 멤버가 부족했다.

+1

[왜 성능에 좋지 객체의 프로토 타입을 돌연변이인가? (에 허용 대답 http://stackoverflow.com/questions/23807805/why-is-mutating-the-prototype-of-an -object-bad-for-performance)에는 관심이있을만한 정보와 따옴표가 있습니다. – noppa

답변

4

그렇다면 __proto__의 경우 또는 좋거나 나쁜 용도는 무엇입니까?

__proto__, 1 코드에서 그렇게 할 필요가 없습니다 설정 에 대한 좋은 사용 사례가 있는지 여부를 차치.대신 :

없이 프로토 타입 루트 만들기 :

rootStyle = Object.create(null); 

프로토 타입으로 rootStyle 사용하여 객체를 만들기 : 다른 변경하지 않고 코드의 시작 부분에 그 적용

elem[0].style = Object.create(rootStyle); 

를 :

var rootStyle = Object.create(null),   // ** 
    elem = [{}, {}, {}]; 

rootStyle.fontSize = '14px'; 

elem[0].style = Object.create(rootStyle);  // ** 
elem[0].style.fontWeight = 'bold'; 
elem[0].className = 'my-elem-123'; 

elem[1].style = Object.create(rootStyle);  // ** 
elem[1].style.fontStyle = 'italic'; 
elem[1].className = 'my-elem-456'; 

elem[2].style = Object.create(elem[1].style); // ** 
elem[2].style.textDecoration = 'underline'; 
elem[2].className = 'my-elem-789'; 
elem[0].domNode = document.body.childNodes[0]; 
elem[1].domNode = document.body.childNodes[1]; 
elem[2].domNode = elem[1].domNode.childNodes[0]; 

elem 인스턴스의 프로토 타입 체인의 특성 당신이 할 경우 발생하는 문제에 완전히 무관하다 :이 같은 ELEM 배열의 실제 DOM 노드에 대한 참조를 저장하는 경우 무슨 일이 일어날 지위.

위의 작업을 수행하면 "일어날 일"에 대한 대답은 다음과 같습니다. (IE의 구식 버전을 사용하지 않는 한) 특별한 것은 없습니다. 이 요소에 대한 또 다른 참조이므로, document.body의 첫 번째 자식을 제거한 후에 (정리하면) 정리하지 말고 elem[0].domNode에 대한 참조를 삭제할 때까지 계속 붙어 있지만 그 때와 다를 바 없습니다. 다른 객체에 대한 참조를 유지합니다 (IE의 구식 버전에 대해 언급하지 않는 경우). 그에


1 세 노트 :

  1. 당신이, 기존 개체의 프로토 타입을 변경 한 걸음 뒤로 물러나와 전체 디자인을 볼 필요가 있다고 생각하는 경우

    . 그렇게하는 것이 매우 드문 경우입니다. 일반적으로 올바른 유형의 새로운 객체를 만들고 관련 정보를 복사하는 디자인 관점에서 더 유리합니다. (나는 10 년 동안 자바 스크립트 프로그래밍을 잘 해왔다. 고전적인 OOP 용어 [C++, Java]에 넣는다면 객체를 생성 한 후에 객체의 유형을 변경하는 것과 같을 것이다. Cat,하지만 지금은 Dog로를 변경하고 싶습니다. 그냥 그렇게 겠다는 필요성을 가지고 하고서 드물다.)

  2. 당신이 MDN에서 본 것처럼

    , 객체의 프로토 타입 변경 자바 스크립트 엔진이 최적화 된 것이 아니기 때문에 아웃 라이어의 경우 객체의 최적화를 날려 버려 속성 액세스 속도가 느려지는 경향이 있습니다. 어느 정도 속도가 느려지는지 여부는 입니다. 물론 유스 케이스에서 유스 케이스까지 다양합니다. 문제가 발생하기 전에 그것에 대해 걱정하는 것은 조숙 한 최적화 일 것입니다. 당신이 경우 현대 자바 스크립트 엔진에

  3. 는 프로토 타입을 변경하는 정품 사용 사례가 오히려 __proto__에 할당하는 것보다 Object.setPrototypeOf을 통해 그것을 할.

+0

하지만이 모양은 다음과 같습니다. C++은 OOP 언어이지만 사용자 지정 클래스를 만드는 것은 매우 바람직하지 않습니다.아니면 프로토 타입을 변경하는 것이 느린 작업입니까? (그렇다면 항상 염두에두면 문제가되지 않습니다.) 그리고 객체의 최적화를 날려 버리는 경우는 확실합니까? 예를 보여줄 수 있습니까? 아니면 극도로 깊은 프로토 타입 체인을 의미합니까? – user3198882

+0

좋아, 내가 그것을 얻을 것처럼 보이는데, 나는 사용자 정의 프로토 타입을 사용할 수 있지만, Object.create (null) 및 다른 구문을 사용하여 답변을 격려했다. 최적화에 대해서는 공통된 프로그래밍 실수를하지 않는다면 아무런 문제가 없습니다 (프로토 타입 체인 조회가 어떻게 작동하는지 명심하십시오). – user3198882

+1

@ user3198882 : * 기존 * 객체의 프로토 타입을 변경할 필요가있는 상황이 매우 드뭅니다. Object.create 또는 생성자 함수를 사용하여 올바른 프로토 타입으로 객체를 생성하면됩니다. –

관련 문제