왜 document.write가 "나쁜 습관"으로 간주됩니까?


363

나는 document.write나쁜 습관으로 간주된다는 것을 안다 . 그리고 제 3 자 공급 업체에 제출하여 document.write분석 코드 구현에 사용해서는 안되는 이유에 대한 이유 목록을 작성하고 싶습니다 .

document.write아래에 잘못된 관행 이라고 주장한 이유를 포함하십시오 .

답변:


243

더 심각한 문제 중 몇 가지 :

  • XHTML에서는 document.write (이후 DW)가 작동하지 않습니다

  • DW는 DOM을 직접 수정하지 않으므로 추가 조작을 방지 할 수 있습니다 (증거를 찾으려고하지만 상황이 가장 좋습니다).

  • 페이지로드가 완료된 후 실행 된 DW는 페이지를 덮어 쓰거나 새 페이지를 쓰거나 작동하지 않습니다.

  • DW는 마주 친 곳에서 실행됩니다. 주어진 노드 포인트에 주입 할 수 없습니다

  • DW는 직렬화 된 텍스트를 효과적으로 작성합니다. 이는 DOM이 개념적으로 작동하는 방식이 아니며 버그를 만드는 쉬운 방법입니다 (.innerHTML도 같은 문제가 있습니다)

안전하고 DOM 친화적 인 DOM 조작 방법 을 사용하는 것이 훨씬 좋습니다


39
-1, DOM을 절대적으로 수정합니다. 다른 모든 것은 괜찮습니다. 해를 입지 않도록 구조와 방법에 의존해야한다는 충동을 이해하지만, 목욕물을 가지고 아기를 쫓아내는 경우가 있습니다.
cgp

7
FireBug는 DOM의 진정한 표현이 아닙니다. HTML을 DOM으로 구문 분석하는 것은 mozilla의 시도입니다. Firebug DOM보기에서 HTML이 완전히 깨져 보일 수 있습니다.
FlySwat

8
DOM은 페이지를 렌더링하는 데 사용되는 데이터 구조이며 페이지에서 사용자가 보는 것의 알파 및 오메가입니다. HTML! = DOM이라는 것이 맞지만 DW가 DOM을 수정하는지 여부는 중요하지 않습니다. DW가 DOM을 수정하지 않은 경우 화면이 표시되지 않습니다. 이는 모든 브라우저에 해당되며 DOM이 페이지를 렌더링하는 데 사용되는 한 항상 길어야합니다.
cgp

8
"DW는 만난 곳에서 실행" -항상 단점은 아니지만 실제로는 스크립트 요소 추가 (실제로 DW를 사용하는 유일한 요소, 심지어 두 번 생각하는 것)와 같은 특정 요소의 이점으로 간주 될 수 있습니다. .
nnnnnn

7
@RicardoRivaldo 예, document.write문서 로딩이 완료된 후 호출 되면
Izkata

124

실제로 document.write는 그 자체로 는 아무런 문제가 없습니다 . 문제는 오용하기가 정말 쉽다는 것입니다. 심하게도.

Google 애널리틱스와 같은 애널리틱스 코드를 제공하는 벤더 측면에서 실제로 이러한 스 니펫을 배포하는 가장 쉬운 방법입니다

  1. 스크립트를 작게 유지합니다
  2. 이미 설정된 onload 이벤트를 재정의하거나 onload 이벤트를 안전하게 추가하기 위해 필요한 추상화를 포함 할 것에 대해 걱정할 필요가 없습니다.
  3. 매우 호환됩니다

만큼 당신이 문서가로드 된 후 그것을 사용하려고하지 않는 한 ,document.write내 소견으로, 본질적으로 악하지 않다.


3
document.write는 html 파서에게 정말 끔찍한 일을하며 간단한 경우에는 "매우 호환"됩니다.
olliej

27
분석 태그 삽입처럼? 결국, 원래 질문의 일부입니다. 그리고 매우 호환 가능하다는 것은 document.write 메소드에 대한 원시 브라우저 지원을 의미합니다.
Peter Bailey

최신 버전의 Chrome / IE / Safari / Opera / FireFox에서 작동하는 것은 호환되는 것으로 간주됩니다.
Pacerier

2
온로드 이벤트를 재정의 하시겠습니까? 그리고 무엇을 addEventListener위해?
m93a

Chrome은 document.write특정 조건이 충족되면 스크립트를 삽입하는 호출을 실행하지 않습니다 .
Flimm

44

또 다른 합법적 인 사용은 document.writeHTML5 Boilerplate index.html 예제 에서 비롯됩니다 .

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>

또한 json2.js JSON 구문 분석 / stringify polyfill ( IE7 이하에서 필요) 을 사용하는 것과 동일한 기술을 보았습니다 .

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>

11
여기서는 나쁜 사용은 아니지만 DOM 조작 기능을 사용하는 것이 "더 나은"것입니다. Google도 Google 웹 로그 분석을 위해 사용합니다. 스 니펫이 여기 있습니다 .
BMiner

8
@BMiner scriptDOM 조작을 통해 요소를 삽입하면 동기식으로로드됩니까? 그렇지 않으면 대체품이 아닙니다.
John Dvorak

2
@ JanDvorak-좋은 지적; DOM 조작을 사용할 때 브라우저는 일반적으로 스크립트를 비동기 적으로로드합니다. 당신은 사용할 수 있습니다 onload비동기식으로로드 된 스크립트를 사용할 수있을 때 결정하기 위해 DOM 이벤트를.
BMiner

1
@JanDvorak 외부에 있지 않으면 (동기화되지 않은 경우 src) 동기식으로로드됩니다 . 그렇지 않으면 비동기 적으로 "가능한 빨리"실행됩니다.
Oriol

1
사용자가 2G 연결을 사용하는 경우 Chrome에서 의도적으로 태그 document.write를 삽입 하는 호출 을 실행하지 않기 때문에 여전히 중단 될 수 있습니다 <script>. 참조 developers.google.com/web/updates/2016/08/...
Flimm

42

페이지를 차단할 수 있습니다

document.write페이지가로드되는 동안에 만 작동합니다. 페이지로드가 완료된 후 호출하면 전체 페이지를 덮어 씁니다.

즉, 인라인 스크립트 블록에서 호출해야합니다. 그러면 브라우저가 다음 페이지의 일부를 처리하지 못합니다. 쓰기 블록이 완료 될 때까지 스크립트와 이미지는 다운로드되지 않습니다.


31

찬성:

  • 외부 (호스트 / 도메인) 스크립트에서 인라인 컨텐츠를 포함하는 가장 쉬운 방법입니다.
  • 프레임 / iframe에서 전체 내용을 덮어 쓸 수 있습니다. 더 현대적인 Ajax 기술이 널리 사용되기 전에 (1998-2002) 메뉴 / 탐색 조각에이 기술을 많이 사용했습니다.

범죄자:

  • 이 스크립트는 외부 스크립트가로드 될 때까지 일시 중지되도록 렌더링 엔진을 직렬화하여 내부 스크립트보다 훨씬 오래 걸릴 수 있습니다.
  • 일반적으로 스크립트가 내용 내에 배치되는 방식으로 사용되며 이는 잘못된 형식으로 간주됩니다.

3
그보다 더 많은 단점이 있습니다. 예를 들어 특정 상황에서 태그 document.write를 생성 하는 Chrome의 실행 을 거부합니다 <script>. developers.google.com/web/updates/2016/08/…
Flimm

@Flimm 주목할 가치가 있습니다. 귀하의 의견은 답변 후 8 년이 넘었으며 거의 ​​3 년이 지났습니다. 예, 다른 단점이 있습니다 ... document.write 자체가 사라지지 않는 경우뿐만 아니라 다른 악용이 심한 인터페이스도 놀랍습니다.
트래커 1

10

여기에 두 가지 가치가 있습니다. 일반적으로 document.write무거운 물건을 들어서는 안되지만 확실히 유용한 한 가지 예가 있습니다.

http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html

최근에 AJAX 슬라이더 갤러리를 만들려는 것을 발견했습니다. 두 개의 중첩 된 div를 만들고 JS로 width/ heightoverflow: hidden외부에 적용했습니다 <div>. 브라우저가 JS를 사용하지 않도록 설정 한 경우 div가 갤러리의 이미지를 수용 할 수 있도록 떠 오릅니다.

위의 기사와 마찬가지로 CSS의 JS 하이재킹은 페이지가로드 될 때까지 시작되지 않아 div 가로 드 될 때 순간적으로 플래시가 발생했습니다. 따라서 페이지가로드 될 때 CSS 규칙을 작성하거나 시트를 포함해야했습니다.

분명히 이것은 XHTML에서 작동하지 않지만 XHTML은 죽은 오리의 것으로 보이므로 IE에서 태그 수프로 렌더링되므로 DOCTYPE 선택을 다시 평가할 가치가 있습니다 ...


7

가장 명백한 이유 인 페이지의 내용을 덮어 쓰지만 "나쁜"것으로 부르지는 않습니다.

JavaScript를 사용하여 전체 문서를 작성하지 않으면 document.write로 시작할 수 없다면 많이 사용하지 않습니다.

그럼에도 불구하고 document.write를 사용할 때 DOM을 실제로 활용하지는 않습니다. 문서에 텍스트 덩어리를 덤핑하여 형식이 잘못되었다고 말할 수 있습니다.


2
한 가지 설명 : document.write는 페이지에 내용을 삽입하지만 내용을 덮어 쓰지 않습니다.
Peter Dolberg

5
@Peter, 문서를로드 한 후 호출하면 내용을 덮어 씁니다. 나는 그것이 aleemb이 의미하는 것 같아요.
Matthew Crumley

2
대신 비슷한 작업을 수행하는 대신 코드에서 개별 DOM 노드를 수동으로 빌드해야한다고 제안하고 div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";있습니까? 그것은 불필요하고 읽기 어려운 코드를 많이 생성하는 것처럼 보입니다. John Resig와 다른 JS 개발자들이 옹호하는 접근법과는 정반대입니다.
Lèse majesté

7

XHTML 페이지와 같은 XML 렌더링을 사용하여 페이지를 분할합니다.

최고 : 일부 브라우저는 HTML 렌더링으로 다시 전환되며 모든 것이 잘 작동합니다.

가능성 : 일부 브라우저는 XML 렌더링 모드에서 document.write () 함수를 비활성화합니다.

최악 : 일부 브라우저는 document.write () 함수를 사용할 때마다 XML 오류를 발생시킵니다.


6

내 머리 꼭대기에서 :

  1. document.write페이지로드 또는 본문로드에 사용해야합니다. 따라서 다른 시간에 스크립트를 사용하여 페이지 내용을 업데이트하려는 경우 document.write는 거의 쓸모가 없습니다.

  2. 기술적으로 document.write XHTML / XML이 아닌 HTML 페이지 만 업데이트합니다. IE는이 사실을 꽤 용서하는 것처럼 보이지만 다른 브라우저는 그렇지 않습니다.

http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite


9
IE는 XHTML을 지원하지 않기 때문에 용서하고 있습니다. 그렇다면 / document.write는 아마도 작동을 멈출 것입니다 (물론 XHTML에서만).
Matthew Crumley

2
XHTML은 웹과 관련이 없습니다. 엄격한 XHTML doctype을 가진 페이지조차도 실제로 XML로 취급되지 않으며, 브라우저 개발자는 페이지 작성자 그렇게 신뢰하지 않습니다 .
RobG

4

document.write경우에 따라 스크립트를 삽입하는 Chrome이 차단 될 수 있습니다 . 이 경우 콘솔에 다음 경고가 표시됩니다.

파서 차단, 교차 출처 스크립트 ...는 document.write를 통해 호출됩니다. 장치의 네트워크 연결 상태가 좋지 않으면 브라우저에 의해 차단 될 수 있습니다.

참고 문헌 :


3

브라우저 위반

.write파서가 페이지를 렌더링하지 못하도록 브라우저 위반으로 간주됩니다. 파서는 문서가 수정되고 있다는 메시지를받습니다. 따라서 JS가 프로세스를 완료 할 때까지 차단됩니다. 이때에만 파서가 재개됩니다.

공연

이러한 방법을 사용하면 가장 큰 결과로 성능이 저하됩니다. 브라우저는 페이지 내용을로드하는 데 시간이 더 걸립니다. 로드 시간에 대한 부작용은 문서에 기록되는 내용에 따라 다릅니다. 추가하면 큰 차이가 보이지 않습니다.<p>JavaScript 라이브러리에 50-some 참조 배열을 전달하는 것과 반대로 DOM에 태그를 물론 하드웨어에 따라 다릅니다).

도움이 될 수 있다면이 방법을 피하는 것이 가장 좋습니다.

자세한 내용은 document.write ()에 대한 개입을 참조하십시오.


3

Google-Chrome Dev Tools의 Lighthouse Audit 에서 수행 한 분석을 기반으로 ,

연결 속도가 느린 사용자의 경우 동적으로 삽입 된 외부 스크립트 document.write()는 페이지로드를 수십 초 지연시킬 수 있습니다.

여기에 이미지 설명을 입력하십시오


2
  • document.write나쁜 습관이 있는 간단한 이유 는 더 나은 대안을 찾을 수없는 시나리오를 만들 수 없기 때문입니다.
  • 또 다른 이유는 객체 대신 문자열을 다루기 때문입니다 (매우 원시적입니다).
  • 문서에만 추가됩니다.
  • 예를 들어 MVC (Model-View-Controller) 패턴 의 아름다움은 없습니다 .
  • ajax + jQuery 또는 angularJS로 동적 컨텐츠를 표시하는 것이 훨씬 강력합니다 .

첫 번째 글 머리 기호에 관해서는 위의 답변에서 @sunwukung이 설명 한 것을 어떻게 해결할 것입니까? DOM 조작으로 해결할 수 있다는 데 동의 하지만 DOM 조작이 진행됨에 따라 때로는 FUOC를 피하기가 어렵습니다 document.write.
bert bruynooghe

FUOC가 더 이상 문제입니까?
Anders Lindén

1

document.write () (및 .innerHTML)를 소스 코드 문자열을 평가하는 것으로 생각할 수 있습니다. 많은 응용 프로그램에 매우 유용 할 수 있습니다. 예를 들어 어떤 소스에서 HTML 코드를 문자열로 얻는다면 그냥 "평가"하는 것이 편리합니다.

Lisp와 관련하여 DOM 조작은 목록 구조를 조작하는 것과 같습니다 (예 : 다음을 수행하여 목록 (주황색) 작성).

(cons 'orange '())

그리고 document.write ()는 문자열을 평가하는 것과 같습니다. 예를 들어 다음과 같이 소스 코드 문자열을 평가하여 목록을 만듭니다.

(eval-string "(cons 'orange '())")

또한 Lisp에는 목록 조작을 사용하여 코드를 작성하는 데 매우 유용한 기능이 있습니다 (예 : "DOM 스타일"을 사용하여 JS 구문 분석 트리 작성). 즉, "문자열 스타일"대신 "DOM 스타일"을 사용하여 목록 구조를 작성한 다음 해당 코드를 실행할 수 있습니다 (예 : 다음과 같이).

(eval '(cons 'orange '()))

간단한 라이브 편집기와 같은 코딩 도구를 구현하는 경우 예를 들어 document.write () 또는 .innerHTML을 사용하여 문자열을 빠르게 평가할 수있는 기능이 매우 편리합니다. Lisp는 이런 의미에서 이상적이지만 JS에서도 매우 멋진 작업을 수행 할 수 있으며 http://jsbin.com/ 과 같이 많은 사람들이 그렇게하고 있습니다.


1

document.write의 단점은 주로 다음 세 가지 요소에 따라 다릅니다.

a) 구현

document.write ()는 내용이 필요한 즉시 내용을 화면에 쓰는 데 주로 사용됩니다. 이는 JavaScript 파일 또는 HTML 파일 내의 스크립트 태그 내에서 발생합니다. 스크립트 태그가 이러한 HTML 파일의 어느 곳에 나 배치되면 웹 페이지 내의 HTML과 얽힌 스크립트 블록 내에 document.write () 문을 갖는 것이 좋지 않습니다.

b) 렌더링

잘 설계된 코드는 일반적으로 동적으로 생성 된 컨텐츠를 가져 와서 메모리에 저장하며, 코드가 화면에 튀어 나오기 전에 코드를 통과 할 때 계속 조작합니다. 따라서 이전 섹션의 마지막 요점을 되풀이하기 위해 적절한 위치에 컨텐츠를 렌더링하면 신뢰할 수있는 다른 컨텐츠보다 더 빠르게 렌더링 할 수 있지만 처리를 위해 컨텐츠를 렌더링해야하는 다른 코드에서는 사용할 수 없습니다. 이 딜레마를 해결하려면 document.write ()를 제거하고 올바른 방법으로 구현해야합니다.

c) 불가능한 조작

일단 작성되면 끝났습니다. DOM을 두드리지 않고는 다시 조작 할 수 없습니다.


1

나는 document.write를 사용하는 것이 나쁜 습관이라고 생각하지 않습니다. 간단히 말해서 그것은 경험이없는 사람들에게는 고전압과 같습니다. 잘못 사용하면 요리됩니다. 이 방법과 다른 위험한 방법을 한 번 이상 사용한 많은 개발자가 있으며 실제로는 절대 실패하지 않습니다. 대신, 무언가 잘못되면, 그들은 구제되고 더 안전한 것을 사용합니다. 이들은 "나쁜 습관"으로 간주되는 것에 대해 그러한 진술을하는 사람들입니다.

파일을 몇 개만 삭제 한 다음 "드라이브 포맷팅은 좋지 않습니다"라고 말하면 하드 드라이브를 포맷하는 것과 같습니다.


-3

가장 큰 문제는 document.write를 통해 작성된 요소가 페이지 요소 끝에 추가된다는 것입니다. 현대적인 페이지 레이아웃과 AJAX에서 원하는 효과는 거의 없습니다. (DOM의 요소는 일시적이며 스크립트가 실행될 때 동작에 영향을 줄 수 있음을 명심해야합니다.)

페이지에 자리 표시 자 요소를 설정 한 다음 innerHTML을 조작하는 것이 훨씬 좋습니다.


15
사실이 아닙니다. document.write는 페이지의 끝에 내용을 추가하는 것처럼 내용을 추가하지 않습니다. 그들은 그 자리에 쓰여졌습니다.
피터 베일리

1
@ 피터 베일리, 나는 이것이 오래된 스레드라는 것을 알고 있지만 실제로 이것은 다운 투표해서는 안됩니다. 추가 여부는 페이지가로드되는 동안 document.write ()가 인라인으로 실행되는지에 따라 다릅니다. 페이지가로드 된 후 함수에서 호출되면 첫 번째 document.write ()가 전체 본문을 대체하고 후속 호출이 추가됩니다.
Octopus

3
@Octopus 네,하지만 정황입니다. 이 시나리오에서는 새로운 문서가 있기 때문에 추가됩니다. "document.write () adds"라고 말하는 것은 여전히 ​​정확하지 않습니다. 그렇습니다. 오래된 대답이자 오래 된 공감이지만 여전히 그 옆에 있습니다.
Peter Bailey

괜찮아. 나는 부정확하게 말했다. 오래 전에 편집했지만 위의 답변이 훨씬 낫습니다. 나는 "제자리에 쓰여진"것도 똑같이 부정확하다고 지적합니다.
BnWasteland
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.