ID가있는 DOM 트리 요소가 전역 변수가됩니까?


364

간단한 HTMLElement 래퍼에 대한 아이디어를 연구하면서 Internet Explorer 및 Chrome 에서 다음을 우연히 발견했습니다 .

DOM 트리에 ID가있는 지정된 HTMLElement의 경우 ID를 변수 이름으로 사용하여 div를 검색 할 수 있습니다. 그래서 같은 사업부

<div id="example">some text</div>

인터넷 익스플로러 8 과 크롬 당신은 할 수 있습니다 :

alert(example.innerHTML); //=> 'some text'

또는

alert(window['example'].innerHTML); //=> 'some text'

그렇다면 이것이 DOM 트리의 모든 요소 가 전역 네임 스페이스의 변수로 변환 된다는 의미 입니까? 그리고이 getElementById브라우저 에서 메소드를 대신하여 이것을 사용할 수 있습니까?



1
@ Bergi,이를하지 말라고 언급 한 의견은 이제 구식이며 심지어 유효하지 않습니다. 따라서이 기능을 사용하지 않는 확실한 이유를 찾을 수 없습니다.
ESR

@EdmundReed 링크 된 질문에 대한 답을 다시 읽고 싶을 수도 있습니다. " 암시 적으로 선언 된 전역 변수 "는 툴링 지원이없고 " 취약한 코드로 이어집니다 " 라는 나쁜 생각 입니다. "기능"이라고 부르지 마십시오. 아래 답변은 호환성 이유로 표준의 일부가 된 버그에 대해 설명합니다.
Bergi

1
@Bergi 공정, 당신이 맞아요. 나는 아직도 그것이 정말 깔끔한 기능이라고 생각하며 사람들이 그것을 알지 못하기 때문에 문제가되는 것으로 간주됩니다. 이것이 내가 그것을 사용하는 방법입니다 : codepen.io/esr360/pen/WEavGE?editors=1000#0
ESR

@EdmundReed 물론 내용과 논리를 올바르게 분리하지 않으면 문제가 줄어 듭니다. 또한 인라인 이벤트 핸들러를 사용하거나 네임 스페이스로 남용하는 DOM 요소에 사용자 정의 메소드를 설치하지 않는 것이 좋습니다 ( "범위"가 아님).
Bergi

답변:


395

발생하는 것은 '명명 된 요소'가 document객체의 명백한 속성으로 추가된다는 것입니다 . 요소 이름이의 실제 속성과 충돌 할 수 있기 때문에 이것은 정말 나쁜 생각입니다 document.

IE는 명명 된 요소를 window개체의 속성으로 추가하여 상황을 악화 시켰습니다 . 이것은 객체 document또는 window객체 (또는 프로젝트의 다른 라이브러리 코드)의 멤버가 사용하려고 할 때 요소의 이름을 지정하지 않아야한다는 점에서 두 배로 나쁩니다 .

또한 이러한 요소가 전역 유사 변수로 표시됨을 의미합니다. 운 좋게도이 경우 코드에서 실제 전역 var또는 function선언은 그림자로 표시되므로 이름 지정에 대해 너무 걱정할 필요가 없지만 충돌하는 이름으로 전역 변수에 할당을 시도하고 선언하는 것을 잊어 버린 경우 그것은 var요소 자체에 값을 할당하려고 할 때 IE에서 오류가 발생합니다.

일반적으로 생략 하거나 var명명 된 요소에 표시 window되거나 전역 으로 표시되는 것은 나쁜 습관으로 간주됩니다 . 에 스틱 document.getElementById더 광범위하게 지원하고 덜 모호한된다. 타이핑이 마음에 들지 않으면 더 짧은 이름으로 간단한 래퍼 함수를 ​​작성할 수 있습니다. 어쨌든 브라우저는 일반적으로 getElementById빠른 조회를 사용 하도록 호출을 최적화하기 때문에 id-to-element 조회 캐시 를 사용할 필요가 없습니다. 요소가 변경 id되거나 문서에서 추가 / 제거 될 때 문제가 발생 합니다.

오페라는 IE가, 다음에 합류 웹킷, 그리고 명명 된 요소를 넣어 지금 모두 이전에 unstandardised 연습 복사 document속성 및에 이르렀의 이전 IE 전용 연습 window하는 중인 표준화 누구의 접근 문서이며 모든 표준화 HTML5에 의해 브라우저 작성자가 우리에게 끔찍한 관행을 가해 웹의 일부로 영원히 만들었습니다. 따라서 Firefox 4도이를 지원합니다.

'명명 된 요소'란 무엇입니까? 와 함께 id, 그리고 name'식별'목적으로 사용되는 모든 것 , 즉 폼, 이미지, 앵커 및 기타 몇 가지이지만 name폼 입력 필드의 컨트롤 이름, <param>또는 메타 데이터 유형입니다 <meta>. '식별하기' name는 찬성하여 피해야 할 것들입니다 id.


5
분명한 대답입니다. 감사합니다. document.getElementById를 생략하는 것은 제 생각이 아닙니다 (물론 요즘에는 요소 / 요소 속성을 찾을 수있는 경우 xpath를 사용합니다). 나는 명명 된 아이템에 대한이 (나쁜) 연습을 우연히 발견했고 그것이 어디에서 왔는지 궁금했다. 당신은 그 시간에 충분히 대답했습니다. 이제 Chrome (웹킷)에서도 찾을 수있는 이유를 알았습니다.
KooiInc

18
"사용을 name피해야합니다" 의 한 가지 예외 는입니다 <input>. 여기서 name속성은 양식 제출을위한 키-값 쌍의 키를 형성하는 데 중요한 역할을합니다.
Yahel

7
참고 Firefox는 쿼크 모드에있을 때만이 작업을 수행합니다.
Crescent Fresh

4
@ yahelc : 그것은 내가 만들고있는 구별입니다. " name양식 입력 필드에서 유사한 제어 이름을 다른 용도로 사용하지 않습니다 ..."
bobince

13
왜!? 이 광기를 막기 위해 할 수있는 일이 있습니까? 내 함수는 요소에 대한 참조로 재정의되었으며 디버깅하는 데 한 시간이 걸렸습니다. :(
Farzher

52

이전 답변에서 언급했듯이이 동작은 창 개체에 대한 명명 된 액세스라고합니다 . 의 값 name일부 요소에 대한 속성과 값 id의 모든 요소에 대한 속성은 세계의 속성으로 사용할 수 있습니다 window객체입니다. 이를 명명 된 요소라고합니다. 이후window브라우저의 전역 객체 각 명명 된 요소는 전역 변수로 액세스 할 수 있습니다.

이것은 원래 Internet Explorer에 의해 추가되었으며 결국이 동작에 종속 된 사이트와의 호환성을 위해 다른 모든 브라우저에서 구현되었습니다. 흥미롭게도 파이어 폭스의 렌더링 엔진 인 Gecko는 이것을 쿼크 모드 에서만 구현하기로 선택 했지만 다른 렌더링 엔진은 표준 모드로 유지했습니다.

그러나 Firefox 14부터 Firefox는 이제window 표준 모드에서도 객체 에 대한 명명 된 액세스지원합니다 . 그들은 왜 이것을 바 꾸었습니까? 표준 모드에서이 기능에 의존하는 사이트가 여전히 많이 있습니다. Microsoft 는 데모를 Firefox에서 사용할 수 없도록 하는 마케팅 데모출시했습니다 .

웹킷은 최근 반대 방향을 고려 하여 window객체의 명명 된 액세스 를 쿼크 모드로만 강등했습니다 . 그들은 Gecko와 같은 추론으로 그것에 반대했습니다.

이 동작은 이제 표준 모드에서 모든 주요 브라우저의 최신 버전에서 사용하는 것이 기술적으로 안전 해 보입니다 . 그러나 명명 된 액세스는 다소 편리해 보일 수 있지만 사용해서는 안됩니다 .

왜? 이 글에서 전역 변수가나쁜지에 대한 많은 추론을 요약 할 수 있습니다 . 간단히 말해서, 추가 전역 변수가 많으면 더 많은 버그가 발생합니다. 실수로 a의 이름을 입력하고 a를 입력한다고 가정 해 봅시다 var.id 하고 DOM 노드 인 SURPRISE .

또한 표준화되었지만 브라우저의 명명 된 액세스 구현에는 여전히 약간의 불일치가 있습니다.

  • IE는 name양식 요소 (입력, 선택 등)에 액세스 할 수 있는 속성 값을 잘못 만듭니다 .
  • Gecko와 Webkit <a>name속성을 통해 태그에 액세스 할 수 없도록 잘못 설정 했습니다 .
  • Gecko는 동일한 이름을 가진 여러 명명 된 요소를 잘못 처리합니다 (참조 배열 대신 단일 노드에 대한 참조를 반환 함).

그리고 가장자리에 명명 된 액세스를 사용하려고하면 더 많은 것이 있다고 확신합니다.

다른 답변에서 언급했듯이에 document.getElementById의해 DOM 노드에 대한 참조를 얻는 데 사용 됩니다 id. name속성 으로 노드에 대한 참조를 가져와야하는 경우 use를 사용하십시오 document.querySelectorAll.

사이트에서 명명 된 액세스를 사용하여이 문제를 전파하지 마십시오. 많은 웹 개발자들이이 마술 을 추적하는 데 시간을 낭비했습니다 행동 . 표준 모드에서 명명 된 액세스를 끄려면 조치를 취하고 렌더링 엔진을 가져와야합니다. 단기적으로는 일부 사이트가 나쁜 일을하게되지만 장기적으로 웹을 발전시키는 데 도움이 될 것입니다.

관심이 있으시면 내 블로그 ( https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/) 에서 이에 대해 자세히 설명합니다 .


3
"사용해서는 안된다"는 전제에 대한 명백한 경고에 대한 참고 사항. 즉, "코드 카우보이가되는 경우를 제외하고는 사용해서는 안됩니다." 코드 카우보이는 그냥 간다.
Jeremy Foster

5
"코드 카우보이"가 개발자에게 친숙하지 않은 나쁜 구현을 사용하고 전파하는 사람을 의미하지 않는 한 @jeremyfoster는 매우 동의하지 않습니다.
Patrick Roberts

2
좋은 카우보이의 표식은 많은 사람들이 동의하지 않는다는 것입니다. 하지만 지금은 철학적 카우보이 나 그와 비슷한 사람입니다.
Jeremy Foster

더 많은 사람들이 DOM을 사용 document.querySelectorAll하고 document.querySelector액세스 할 때 그것을 사용하는 좋은 제안에 +1. 선택기로 요소에 액세스하는 것이 확실히 더 효율적인 프로세스입니다.
Travis J

20

getElementById()예를 들어 다음과 같은 경우에 충실해야합니다 .

document.getElementById('example').innerHTML

IE는을 가진 요소 혼합을 좋아 name 하고 ID 그래서 가장 잘 얻으려고 노력하는지에 대해 명시 적으로, 글로벌 네임 스페이스 특성을.


3

예, 그렇습니다.


다음 예를 사용하여 Chrome 55, Firefox 50, IE 11, IE Edge 14 및 Safari 10에서 테스트되었습니다 .

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="im_not_particularly_happy_with_that">
    Hello World!
  </div>
  <script>
    im_not_particularly_happy_with_that.innerText = 'Hello Internet!';
  </script>
  <!-- Looking at you W3 HTML5 spec group _ -->
</body>
</html>

http://jsbin.com/mahobinopa/edit?html,output


1
또한 오페라에서. 그러나이 페이지에 표현 된이 메커니즘에 대한 반대 의견은 매우 잘 반영된 것 같습니다.
ncmathsadist

1

질문은 다음과 같이 들릴 것입니다 : "제공된 ID를 가진 HTML 태그가 전 세계적으로 접근 가능한 DOM 요소가됩니까?"

대답은 '예'입니다.

그것이 작동하는 방식이고, 이것이 W3C에 의해 ID가 도입 된 이유입니다. 파싱 ​​된 스크립팅 환경에서 HTML 태그의 ID는 해당 DOM 요소 핸들이됩니다.

그러나 Netscape Mozilla는 W3C를 준수하지 않기를 거부했으며 더 이상 사용되지 않는 Name 속성을 사용하여 혼란을 일으켰으므로 W3C의 고유 ID 도입으로 인한 스크립팅 기능과 코딩 편의성을 깨뜨 렸습니다.

Netscape Navigator 4.7이 실패한 이후 개발자들은 모두 W3C에 침투 한 반면, 직원들은 잘못된 관행과 오용 사례로 웹을 대체했습니다. ID 속성과 동등하게 이미 더 이상 사용되지 않는 Name 속성 [! 독특하지 않아야 함]을 사용하고 재사용하여 특정 DOM 요소에 액세스하기 위해 ID 핸들을 사용한 스크립트가 간단하게 중단되었습니다!

그리고 적어도 코딩을 비효율적으로 만들고 브라우저를 단순히 깨지 않았을 때 더 많은 오버 헤드를 제공하는 document.all.ElementID.property대신 광범위한 코딩 레슨과 예제 [그들의 ​​브라우저는 어쨌든 인식하지 못합니다]를 작성하고 게시 할 ElementID.property때처럼 중단했습니다. (현재 [1996-97], 더 이상 사용되지 않음) 이름과 동일한 토큰 값을 제공하는 표준 ID 속성에 동일한 토큰을 사용하여 HTML 도메인.

그들은 무지한 코드 작성 아마추어의 압도적 인 군대가 이름 속성과 ID 속성이 더 짧고 따라서 바이트 이름을 절약하고 고대 이름 속성보다 코더에 더 편리하다는 점을 제외하고는 이름과 ID가 거의 동일하다는 것을 쉽게 설득 할 수있었습니다. 물론 거짓말이었다. 또는-HTML로 대체 된 게시 된 기사에서 스크립팅 엔진이 액세스 할 수 있도록 태그에 이름과 ID를 모두 제공해야하는 기사를 설득합니다.

"코드 명"Mozilla "라는 모자이크 살인자들은 너무 화가 나서"우리가 넘어지면 인터넷도 마찬가지 "라고 생각했습니다.

반면에 상승하는 Microsoft는 너무 순진하여 더 이상 사용되지 않고 삭제 Name 속성을 표시해야하며 고유 한 식별자 인 ID 인 것처럼 처리하여 스크립트 기능을 중단하지 않아야한다고 생각했습니다. Netscape 교육생이 코딩 한 이전 페이지 그들은 치명적이었다 ...

ID 충돌 요소의 배열 컬렉션을 반환하는 것은이 의도적 인 인공 문제의 해결책이 아닙니다. 실제로 그것은 모든 목적을 이겼습니다.

그리고 이것이 W3C가 추악하게 변한 유일한 이유 document.getElementById입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.