Удалите все дочерние элементы узла DOM в JavaScript

Как мне удалить все дочерние элементы узла DOM в JavaScript?

Скажем, у меня есть следующий (уродливый) HTML:

<p id="foo">
    <span>hello</span>
    <div>world</div>
</p>

И я беру узел, который хочу, вот так:

var myNode = document.getElementById("foo");

Как я могу удалить потомков foo, чтобы осталось только <p id="foo"></p>?

Могу я просто сделать:

myNode.childNodes = new Array();

или я должен использовать комбинацию removeElement?

Я бы хотел, чтобы ответ был прямым DOM; хотя дополнительные баллы, если вы также предоставите ответ в jQuery вместе с ответом только для DOM.


person Polaris878    schedule 17.10.2010    source источник


Ответы (35)


Вариант 1 A: Очистка innerHTML.

  • Этот подход прост, но может не подходить для высокопроизводительных приложений, поскольку он вызывает анализатор HTML браузера (хотя браузеры могут оптимизировать для случая, когда значением является пустая строка).

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.innerHTML = '';
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via innerHTML</button>

Вариант 1 Б: клиринг textContent

  • То же, что и выше, но используйте .textContent. Согласно MDN, это будет быстрее, чем innerHTML в качестве браузеров не будут вызывать свои анализаторы HTML и вместо этого немедленно заменят все дочерние элементы элемента одним узлом #text.

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  myNode.textContent = '';
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via textContent</button>

Вариант 2 A: Цикл для удаления каждого lastChild:

  • В более раннем редактировании этого ответа использовалось firstChild, но он обновлен для использования lastChild, поскольку в информатике в целом значительно быстрее удалить последний элемент коллекции чем удалить первый элемент (в зависимости от того, как реализована коллекция).
  • Цикл продолжает проверять firstChild на всякий случай быстрее проверять firstChild, чем lastChild (например, если список элементов реализован UA как направленный связанный список).

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.firstChild) {
    myNode.removeChild(myNode.lastChild);
  }
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello</span>
</div>
<button id='doFoo'>Remove via lastChild-loop</button>

Вариант 2 Б. Цикл для удаления каждого lastElementChild:

  • Этот подход сохраняет все не Element (а именно #text узлы и <!-- comments -->) дочерние элементы родительского (но не их потомков) - и это может быть желательно в вашем приложении (например, некоторые системы шаблонов, которые используют встроенные комментарии HTML для хранения инструкций шаблона).
  • Этот подход не использовался до недавнего времени, поскольку Internet Explorer только добавил поддержку lastElementChild в IE9.

doFoo.onclick = () => {
  const myNode = document.getElementById("foo");
  while (myNode.lastElementChild) {
    myNode.removeChild(myNode.lastElementChild);
  }
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <!-- This comment won't be removed -->
  <span>Hello <!-- This comment WILL be removed --></span>
  <!-- But this one won't. -->
</div>
<button id='doFoo'>Remove via lastElementChild-loop</button>

Бонус: Element.clearChildren обезьяна-патч:

  • Мы можем добавить новое свойство-метод к прототипу Element в JavaScript, чтобы упростить его вызов только до el.clearChildren() (где el - любой объект элемента HTML).
  • (Строго говоря, это обезьяна-патч, а не полифилл, поскольку это не стандартная функция DOM или отсутствующая функция. Обратите внимание, что обезьяна-патч по праву не рекомендуется во многих ситуациях.)

if( typeof Element.prototype.clearChildren === 'undefined' ) {
    Object.defineProperty(Element.prototype, 'clearChildren', {
      configurable: true,
      enumerable: false,
      value: function() {
        while(this.firstChild) this.removeChild(this.lastChild);
      }
    });
}
<div id='foo' style="height: 100px; width: 100px; border: 1px solid black;">
  <span>Hello <!-- This comment WILL be removed --></span>
</div>
<button onclick="this.previousElementSibling.clearChildren()">Remove via monkey-patch</button>

person Gabriel McAdams    schedule 17.10.2010
comment
В jQuery можно рассмотреть эти две проблемы: этот метод удаляет не только дочерние (и другие потомки) элементы, но также и любой текст в наборе совпадающих элементов. Это связано с тем, что в соответствии со спецификацией DOM любая строка текста внутри элемента считается дочерним узлом этого элемента. И Чтобы избежать утечки памяти, jQuery удаляет другие конструкции, такие как данные и обработчики событий, из дочерних элементов перед удалением самих элементов. - person jottos; 21.11.2011
comment
@micha Я думаю, ваш тест не подходит. Я написал свой на jsfidle (jsfiddle.net/6K6mv/5), и вот результат . ПОКА: 14 мс; INNERHTML: 7 мс; ТЕКСТОНТЕНТ: 7 мс - person m93a; 02.02.2013
comment
@ m93a: многократный запуск скрипки дает мне результаты от 6 до 11 мс. По сути, это ничего мне не говорит. Результаты ближе друг к другу, чем разница в мс между каждым запуском одного и того же теста. Для справки: это не МОЙ сценарий, это jsperf.com. Посмотрите на это, чтобы лучше понять результаты теста: stackoverflow.com/a/5262617/859877 и stackoverflow.com/questions/4986245/how-does-jsperf-work/ - person micha; 03.02.2013
comment
@micha Да, я знаю, что означают результаты тестов, но это кажется странным. Это показывает мне, что innerHTML на 98% - 99% медленнее. А мои тесты показывают обратное. Но это не чат, я выхожу из обсуждения. - person m93a; 04.02.2013
comment
innerHTML работает только в том случае, если вы имеете дело только с HTML. Если есть, например, SVG внутри только удаление элемента будет работать - person stwissel; 27.03.2013
comment
НИКОГДА НИКОГДА НИКОГДА не используйте innerHTML = ''. Не надо. Проблема в том, что элементы выглядят так, как будто они удалены, но внутренне узлы сохраняются и замедляют работу. У вас есть причина удалить все отдельные узлы. Протестировано как в Google Chrome, так и в IE. Пожалуйста, подумайте об удалении решения innerHTML, поскольку оно неверно. - person Kenji; 21.09.2013
comment
@micha jsperf.com/innerhtml-vs-removechild/151 с использованием .remove () еще быстрее. - person Joeytje50; 11.02.2014
comment
@ joeytje50 Отлично! К сожалению, это DOM4, и он доступен не везде. Я придерживаюсь .removeChild() для лучшей совместимости. К тому же прирост .remove() составляет всего 2%. - person micha; 12.02.2014
comment
Я поместил это в прототип, чтобы мне было проще использовать: Element.prototype.clear = function () {while (this.firstChild) {this.removeChild (this.firstChild);}} - person Abacus; 17.09.2014
comment
@Kenji - что, если я сделаю document.documentElement.replaceChild(newBody, document.body)? будут ли старые элементы и их события сохраняться в памяти? (при замене всего тела элемента) - person vsync; 18.09.2014
comment
@ Андрей Лушников: Зависит от того, в каком браузере и какой версии. На самом деле firstChild лучший в целом: jsperf.com/innerhtml-vs-removechild/250 - person Stefan Steiger; 09.01.2015
comment
@vsync Я не верю, что комментарий Кенджи обоснован. innerHTML = '' выполняется медленнее, но я не думаю, что это неправильно. Любые заявления об утечках памяти должны быть подтверждены доказательствами. - person Chris Middleton; 13.05.2015
comment
@Andrey Lushnikov firstChild и lastChild довольно эквивалентны в моем Chrome 43.0.2357.52 (первый запуск removeChildFirst был немного быстрее, второй запуск removeChildLast выиграл), но оба являются победителями над innerHTML. - person thdoan; 13.05.2015
comment
@Kenji, Наверняка браузер достаточно шустрый, чтобы предотвратить утечку памяти. Удалось ли вызвать утечку памяти в браузере? - person Pacerier; 03.06.2015
comment
Ваши примеры не ошибочны, но я думаю, что в этом ответе есть довольно хороший случай, что тест jsperf был ошибочным, и не измерил то, что должен. (Утверждение в связанном ответе состоит в том, что они удаляли только пустые блоки div, поскольку они ошибочно предполагали, что DOM будет повторно заполняться между каждым тестом.) Другими словами, innerHTML работает быстрее, и есть еще более быстрый метод (замена узлов пустыми единицы). Поскольку ваш ответ получил столько голосов, было бы неплохо, если бы вы вернули эту часть. - person trlkly; 13.02.2016
comment
@Abacus Действуйте осторожно и убедитесь, что браузеры вашей целевой аудитории работают с ним. perfectionkills.com/whats-wrong-with-exnding-the-dom - person gcampbell; 01.10.2016
comment
функция emptyElement (элемент) {var myNode = element; пока (myNode.firstChild) {myNode.removeChild (myNode.firstChild); }} emptyElement (документ.body) - person Marian07; 19.10.2016
comment
(предполагая, что это правда) было бы неплохо иметь причину в ответе - person Old Badman Grey; 27.01.2017
comment
@chharvey Вы изменяете коллекцию, которую активно перебираете, когда используете forEach таким образом. - person Jim Pedid; 03.03.2018
comment
Это смешно. Почему здесь важна производительность? Это 120 кадров в секунду или разовая операция? - person Mars Robertson; 23.12.2018
comment
Я согласен с @MichalStefanow. В этом случае простота кода должна предшествовать минимальному увеличению производительности, если только вы не работаете над конкретным сценарием, требующим такого уровня тщательной оптимизации. При удалении 5-15 узлов разницы не будет. - person Felipe; 11.01.2019
comment
Как новый веб-разработчик, просто хочу сказать, что вы бог. Спасибо за оба метода. Я играл с обоими! - person Gutsygibbon; 03.02.2020
comment
remove дает мне бесконечный цикл на Brave 80.1.5.123. removeChild отлично работает - person OpenSauce; 07.05.2020
comment
Если у меня есть 10 дочерних элементов, которые я хочу удалить, и к каждому из них прикреплено событие, следует ли мне сначала удалить событие, а затем сам элемент, или мне не нужно удалять событие, я могу просто удалить сам элемент ?? (ванильный javascript) - person JustANewCoder; 13.01.2021

В настоящее время принятый ответ неверен, что innerHTML работает медленнее (по крайней мере, в IE и Chrome), как правильно упомянул m93a.

Chrome и FF значительно быстрее при использовании этого метода (который уничтожит прикрепленные данные jquery):

var cNode = node.cloneNode(false);
node.parentNode.replaceChild(cNode, node);

за далекую секунду для FF и Chrome и быстрее всего в IE:

node.innerHTML = '';

InnerHTML не разрушит ваши обработчики событий и не сломает ссылки jquery, он также рекомендуется в качестве решения здесь: https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML.

Самый быстрый метод манипулирования DOM (все еще медленнее, чем два предыдущих) - это удаление диапазона, но диапазоны не поддерживаются до IE9.

var range = document.createRange();
range.selectNodeContents(node);
range.deleteContents();

Другие упомянутые методы кажутся сопоставимыми, но намного медленнее, чем innerHTML, за исключением выброса, jquery (1.1.1 и 3.1.1), который значительно медленнее, чем что-либо еще:

$(node).empty();

Доказательства здесь:

http://jsperf.com/innerhtml-vs-removechild/167 < / strike> http://jsperf.com/innerhtml-vs-removechild/300 https://jsperf.com/remove-all-child-elements-of-a-dom-node-in-javascript (новый URL-адрес для перезагрузки jsperf, потому что редактирование старого URL-адреса не работает)

«Per-test-loop» Jsperf часто понимается как «per-итерация», и только на первой итерации есть узлы для удаления, поэтому результаты бессмысленны, во время публикации в этом потоке были неправильно настроены тесты.

person npjohns    schedule 09.04.2014
comment
Ваш jsperf полностью не работает. Это не очень хорошее доказательство. - person bryc; 15.03.2015
comment
Спасибо, что заметили, что исправили, insertBefore spec изменено и больше не принимает undefined для последнего параметра. - person npjohns; 28.04.2015
comment
На данный момент это лучший ответ. Все остальное в этой ветке - дезинформация (!) Спасибо за очистку всех этих старых плохих тестов. - person Ben; 15.05.2015
comment
InnerHTML не уничтожит ваши обработчики событий и не испортит любые ссылки jquery. Он потеряет данные, хранящиеся в jQuery.cache, что приведет к утечке памяти, потому что единственная доступная ссылка для управления этими данными была на только что уничтоженных вами элементах. - person ; 04.06.2016
comment
InnerHTML не уничтожит ваши обработчики событий и не испортит любые ссылки jquery, относящиеся к контейнеру, а не к дочерним элементам. cloneNode отключает контейнер, что означает, что ссылки на контейнер не поддерживаются (jquery или иначе). Кеш jquery может сделать целесообразным использование jquery для удаления элементов, если к ним прикреплены данные jquery. Надеюсь, они в какой-то момент переключатся на WeakMaps. . Очистка (или даже существование) $ .cache, похоже, официально не задокументирована. - person npjohns; 04.06.2016
comment
jsperf offline, не могли бы вы загрузить сюда свой тестовый код, если он у вас есть? Я бы оценил это! - person radl; 04.09.2016
comment
У меня нет кода, но jsperf в пути backmachine https://web.archive.org/web/20151008164028/http://jsperf.com/innerhtml-vs-removechild/300 - person npjohns; 07.09.2016
comment
Просто случайный вопрос: почему ваш тест включает код для настройки данных, которые будут удалены внутри раздела тестирования? Конечно, настройку следует выполнять вне теста, но все ваши тесты вызывают refreshRange() (который клонирует набор тестовых данных в новый узел) из теста. Как вы можете быть уверены, что это не искажает результаты? - person Periata Breatta; 22.10.2016
comment
Кроме того, почему вы используете contents().remove() в своих тестах jquery (который создает внутренний список всех дочерних узлов, а затем удаляет их), а не empty() (который просто удаляет их)? - person Periata Breatta; 22.10.2016
comment
Все еще не настоящий тест imo. узлы должны быть сгенерированы с присоединенными событиями, атрибутами, функциями и т. д. для более реалистичного теста. В некотором смысле имеет смысл, что removeChild удалит прикрепленные ресурсы, а innerHTML - нет, что будет медленнее, но если вы проводите сравнительный анализ без каких-либо прикрепленных ресурсов, это не имеет смысла. - person Gregoire D.; 12.01.2017
comment
@PeriataBreatta Комментарии jsperf потеряны, но то, что я имел в виду о неисправности, заключалось в выполнении удаления только один раз за тест. Per-test-loop Jsperf часто понимается как per-итерация, и тогда только первая итерация выполняет какую-либо работу, и результаты бессмысленны. Было бы идеально настроить вне итерации, но пока настройка такая же и минимизированная, относительные результаты имеют смысл. Я не знал о empty (), спасибо за внимание, я исправлю. - person npjohns; 24.01.2017
comment
@GregoireD. Эта информация на самом деле не запрашивается в вопросе, и я думаю, что более серьезная проблема использования innerHTML при удалении узлов, вероятно, связана с утечками памяти больше, чем с производительностью, и бросание негерметичной тестовой предпосылки в jsperf, которая не имеет возможности очищать каждую итерацию, вероятно, в конечном итоге исказить результаты - person npjohns; 24.01.2017
comment
Здесь не работают тесты jsperf. Механизм тестирования сообщает следующее: Ошибка: узлы Dom не воссоздаются во время итераций, результаты тестирования будут бессмысленными. - person senderle; 28.03.2017
comment
cloneNode(false) действительно сверхбыстрый, но проблема в том, что поскольку он деструктивен, вам придется повторно ссылаться на свои переменные, что является большим штрафом, например: jsperf.com/innerhtml-vs-removechild/467 - person thdoan; 14.02.2019
comment
Я работаю над курсом DOM, и, поскольку похоже, что jsperf.com - это mia и может быть какое-то время, я создал страницу на jsben.ch. На сегодняшний день победителем остается innerHTML. Я уже слишком долго потратил на эту кроличью нору, но в 2020 году я должен задаться вопросом, почему у нас еще нет .clear() или .empty() метода DOM ... - person Scott Means; 17.08.2020

Используйте современный Javascript с remove!

const parent = document.getElementById("foo")
while (parent.firstChild) {
    parent.firstChild.remove()
}

Это новый способ записи удаления узла в ES5. Это ванильный JS, и он намного лучше читается, чем полагаться на родительский.

Поддерживаются все современные браузеры.

Поддержка браузера - 97% июнь '21

person Gibolt    schedule 15.11.2016
comment
Цикл for не будет работать, поскольку parent.children / parent.childNodes являются активными списками; вызов remove изменяет список, и поэтому ваш итератор не гарантирует итерацию по всему. Например, в Chrome вы пропускаете все остальные ноды. Лучше использовать цикл while (parent.firstChild) { parent.removeChild(parent.firstChild); }. developer.mozilla.org/en-US/docs/Web/ API / ParentNode / children developer.mozilla.org / en-US / docs / Web / API / Node / childNodes - person qix; 16.11.2016
comment
Классная стенография, хотя и менее читаемая: while (parent.firstChild && !parent.firstChild.remove()); - person Gibolt; 08.05.2017
comment
Краткое описание, когда производительность не имеет большого значения: [...parent.childNodes].forEach(el => el.remove()); - person ; 13.08.2018
comment
Это не работает в Typescript ... вместо этого используйте while (selectElem.firstElementChild) { selectElem.firstElementChild.remove(); } - person John Henckel; 20.08.2018

Обновление 2020 - используйте replaceChildren() API!

Заменить всех потомков теперь можно с помощью (поддерживается кроссбраузерность) replaceChildren () API:

container.replaceChildren(...arrayOfNewChildren);

При этом будут выполнены и а) все существующие дочерние элементы, и б) добавление всех заданных новых дочерних элементов за одну операцию.

Вы также можете использовать тот же API, чтобы просто удалить существующие дочерние элементы, не заменяя их:

container.replaceChildren();

Это полностью поддерживается в Chrome / Edge 86+, Firefox 78+ и Safari 14+. (Обратите внимание, что данные MDN в настоящее время неверны для Safari.) Это полностью определенное поведение. Скорее всего, это будет быстрее, чем любой другой предложенный здесь метод, поскольку удаление старых дочерних элементов и добавление новых выполняется а) без необходимости innerHTML, и б) за один шаг, а не за несколько.

person Mason Freed    schedule 22.12.2020

var myNode = document.getElementById("foo");
var fc = myNode.firstChild;

while( fc ) {
    myNode.removeChild( fc );
    fc = myNode.firstChild;
}

Если есть вероятность, что у вас есть потомки, затронутые jQuery, вы должны использовать какой-нибудь метод, который очистит данные jQuery.

$('#foo').empty();

Метод jQuery .empty() гарантирует, что все данные, связанные с jQuery с удаляемыми элементами, будут очищены.

Если вы просто используете DOM методы удаления потомков, эти данные останутся.

person user113716    schedule 17.10.2010
comment
Метод innerHTML на сегодняшний день является наиболее производительным. Тем не менее, данные очищаются с помощью jquery .empty (): удаляет данные () внутри jquery, связанные с дочерними тегами, с помощью рекурсивного цикла (медленно, но может значительно снизить использование памяти), предотвращает утечки памяти, если вы подключили события без jquery, как и использование .onclick = .... Если у вас нет таких событий в дочерних элементах, которые нужно удалить, тогда установка innerHTML не будет протекать. Так что лучший ответ - это зависит от обстоятельств. - person Chris Moschini; 16.11.2011
comment
Почему бы просто не поместить выражение firstChild непосредственно в условие цикла while? while ( myNode.firstChild ) { - person Victor Zamanian; 24.05.2016

Если вы используете jQuery:

$('#foo').empty();

Если вы этого не сделаете:

var foo = document.getElementById('foo');
while (foo.firstChild) foo.removeChild(foo.firstChild);
person PleaseStand    schedule 17.10.2010

Самый быстрый...

var removeChilds = function (node) {
    var last;
    while (last = node.lastChild) node.removeChild(last);
};

Спасибо Андрею Лушникову за ссылку на jsperf.com (классный сайт!).

РЕДАКТИРОВАТЬ: чтобы было ясно, в Chrome нет разницы в производительности между firstChild и lastChild. Верхний ответ показывает хорошее решение для производительности.

person Gabe Halsmer    schedule 02.04.2013
comment
То же самое без предупреждения LINT: clear: function (container) {for (;;) {var child = container.lastChild; если (! ребенок) сломается; container.removeChild (дочерний элемент); }} - person cskwg; 03.01.2019

elm.replaceChildren()

Это экспериментально без широкой поддержки, но при выполнении без параметров будет делать то, что вы просите, и это более эффективно, чем цикл по каждому дочернему элементу и его удаление. Как уже упоминалось, замена innerHTML пустой строкой потребует синтаксического анализа HTML со стороны браузера.

Документация здесь.

person Marc M.    schedule 28.07.2020
comment
Это пока бесполезно только для недавней поддержки браузеров. Но через несколько лет это будет лучший путь. Спасибо, что указали на это. - person leebickmtu; 16.10.2020
comment
caniuse.com/?search=replaceChildren Последняя версия Chrome и Safari только что получила. Подождите пару месяцев. Боже, я люблю автообновления. - person Marc M.; 20.10.2020

Если вы хотите иметь только узел без его дочерних элементов, вы также можете сделать его копию следующим образом:

var dupNode = document.getElementById("foo").cloneNode(false);

Зависит от того, чего вы пытаетесь достичь.

person DanMan    schedule 17.10.2010
comment
Может быть, вы даже могли бы следить за этим с помощью parent.replaceChild(cloned, original)? Это может быть быстрее, чем удаление дочерних элементов по одному, и должно работать со всем, что поддерживает DOM (то есть с каждым типом XML-документа, включая SVG). Установка innerHTML также может быть быстрее, чем удаление дочерних элементов по одному, но это не работает ни с чем, кроме HTML-документов. Должен проверить это когда-нибудь. - person Maarten; 19.06.2012
comment
Это не будет копировать прослушиватели событий, добавленные с помощью addEventListener. - person Matthew; 08.09.2012
comment
Если вы можете жить с этим ограничением, это, безусловно, быстро: jsperf.com/innerhtml-vs-removechild/ 137 - person DanMan; 01.02.2014

Вот еще один подход:

function removeAllChildren(theParent){

    // Create the Range object
    var rangeObj = new Range();

    // Select all of theParent's children
    rangeObj.selectNodeContents(theParent);

    // Delete everything that is selected
    rangeObj.deleteContents();
}
person Nathan K    schedule 11.03.2014
comment
Это интересно, но кажется довольно медленным по сравнению с другими методами: jsperf.com/innerhtml-vs-removechild / 256 - person Polaris878; 06.01.2015

element.textContent = '';

Это как innerText, кроме стандартного. Он немного медленнее, чем removeChild(), но его проще в использовании и не сильно повлияет на производительность, если вы этого не сделаете. У меня слишком много вещей, которые нужно удалить.

person bjb568    schedule 28.03.2014
comment
Текстовый узел не является элементом - person check_ca; 23.04.2014
comment
извините, вы правы, он действительно удаляет все дочерние элементы - person check_ca; 25.04.2014
comment
Это не будет работать в старых версиях Internet Explorer. - person pwdst; 29.03.2017

Вот что я обычно делаю:

HTMLElement.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

И вуаля, позже вы можете очистить любой элемент dom с помощью:

anyDom.empty()
person Ado Ren    schedule 09.09.2018
comment
Мне нравится это решение! По какой причине я должен использовать это вместо установки innerHTML на пустую строку? - person Vim Diesel; 26.10.2019
comment
производительность: domEl.innerHTML = "" неудовлетворительно и считается плохой практикой - person Ado Ren; 27.10.2019

Ecma6 делает его простым и компактным

myNode.querySelectorAll('*').forEach( n => n.remove() );

Это дает ответ на вопрос и удаляет все дочерние узлы.

Если есть текстовые узлы, принадлежащие myNode, их нельзя выбрать с помощью селекторов CSS, в этом случае мы должны применить (также):

myNode.textContent = '';

Фактически последний вариант может быть самым быстрым и более эффективным / действенным решением.

.textContent более эффективен, чем .innerText и .innerHTML, см. MDN

person Marco Balestra    schedule 12.11.2020

В ответ на DanMan, Maarten и Matt. Клонирование узла для установки текста - действительно эффективный способ достижения моих результатов.

// @param {node} node
// @return {node} empty node
function removeAllChildrenFromNode (node) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = removeAllChildrenFromNode( myNode );

Также это работает для узлов не в dom, которые возвращают null при попытке доступа к parentNode. Кроме того, если вам нужно быть в безопасности, узел пуст перед добавлением содержимого, это действительно полезно. Рассмотрим пример использования ниже.

// @param {node} node
// @param {string|html} content
// @return {node} node with content only
function refreshContent (node, content) {
  var shell;
  // do not copy the contents
  shell = node.cloneNode(false);

  // use innerHTML or you preffered method
  // depending on what you need
  shell.innerHTML( content );

  if (node.parentNode) {
    node.parentNode.replaceChild(shell, node);
  }

  return shell;
}

// use as such
var myNode = document.getElementById('foo');
myNode = refreshContent( myNode );

Я считаю этот метод очень полезным при замене строки внутри элемента, если вы не уверены, что будет содержать узел, вместо того, чтобы беспокоиться о том, как навести порядок, начните с нуля.

person jeroen    schedule 15.03.2013
comment
худшая вещь когда-либо. если вы заменяете исходный узел его клоном, вы теряете ссылку на исходный узел. ни один из обработчиков событий и других привязок не будет работать. - person Arun Aravind; 07.12.2013

Мне кажется наиболее естественным использование цикла диапазона:

for (var child of node.childNodes) {
    child.remove();
}

По моим измерениям в Chrome и Firefox, он примерно в 1,3 раза медленнее. В обычных обстоятельствах это, возможно, не имеет значения.

person emu    schedule 06.12.2018

Для этого есть несколько вариантов:

Самый быстрый ():

while (node.lastChild) {
  node.removeChild(node.lastChild);
}

Альтернативы (медленнее):

while (node.firstChild) {
  node.removeChild(node.firstChild);
}

while (node.hasChildNodes()) {
  node.removeChild(node.lastChild);
}

Тест с предложенными параметрами

person magiccrafter    schedule 27.01.2017

var empty_element = function (element) {

    var node = element;

    while (element.hasChildNodes()) {              // selected elem has children

        if (node.hasChildNodes()) {                // current node has children
            node = node.lastChild;                 // set current node to child
        }
        else {                                     // last child found
            console.log(node.nodeName);
            node = node.parentNode;                // set node to parent
            node.removeChild(node.lastChild);      // remove last node
        }
    }
}

Это удалит все узлы в элементе.

person Henrik    schedule 01.02.2014
comment
... потому что это излишне сложно, и я подозреваю, что не дается никаких объяснений относительно того, как это работает (что на самом деле неочевидно). - person Periata Breatta; 23.10.2016

innerText - победитель! http://jsperf.com/innerhtml-vs-removechild/133. Во всех предыдущих тестах внутренний dom родительского узла удалялся на первой итерации, а затем применялся innerHTML или removeChild к пустому div.

person Alexey    schedule 27.01.2014
comment
innerText - это проприетарная вещь MS. Просто говорю. - person DanMan; 01.02.2014
comment
Совершенно уверен, что это ошибочный тест - он полагается на то, что box доступен не как переменная, а через поиск в DOM на основе идентификатора, и поскольку цикл while делает этот медленный вызов много раз, он наказывается. - person nrabinowitz; 10.12.2015

Самый простой способ удалить дочерние узлы узла через Javascript

var myNode = document.getElementById("foo");
while(myNode.hasChildNodes())
{
   myNode.removeChild(myNode.lastChild);
}
person Chaitanya Bapat    schedule 18.07.2016

я видел, как люди делали:

while (el.firstNode) {
    el.removeChild(el.firstNode);
}

тогда кто-то сказал, что использовать el.lastNode быстрее

однако я думаю, что это самый быстрый:

var children = el.childNodes;
for (var i=children.length - 1; i>-1; i--) {
    el.removeNode(children[i]);
}

что ты думаешь?

ps: эта тема мне спасла жизнь. мой аддон firefox был отклонен, потому что я использовал innerHTML. Это давно стало привычкой. тогда я нашел это. и я действительно заметил разницу в скорости. при загрузке innerhtml потребовалось некоторое время для обновления, однако, добавив addElement, это произошло мгновенно!

person Noitidart    schedule 03.02.2014
comment
ну, я думаю, самый быстрый или нет, некоторые тесты jsperf могут доказать любой вариант - person Nikos M.; 06.10.2014
comment
супер работа спасибо за те тесты. они не включают for (var i=0... один. Но вот что я получил, когда провел эти тесты: i.imgur.com/Mn61AmI.png Итак, в этих трех тестах firstNode был быстрее, чем lastNode и innerHTML, что действительно круто - person Noitidart; 06.10.2014
comment
я добавил тесты: jsperf.com/innerhtml-vs-removechild/220 интересные вещи выполнение метода el.firstNode - самый быстрый способ, который кажется - person Noitidart; 06.10.2014

Как правило, JavaScript использует массивы для ссылки на списки узлов DOM. Итак, это будет хорошо работать, если вы заинтересованы в том, чтобы сделать это через массив HTMLElements. Также стоит отметить, что поскольку я использую ссылку на массив вместо прото JavaScript, это должно работать в любом браузере, включая IE.

while(nodeArray.length !== 0) {
  nodeArray[0].parentNode.removeChild(nodeArray[0]);
}
person r00t hkr    schedule 13.07.2017

Почему мы не следуем простейшему методу «удалить» зацикленный внутри while.

const foo = document.querySelector(".foo");
while (foo.firstChild) {
  foo.firstChild.remove();     
}
  • Выбор родительского div
  • Использование метода remove внутри цикла While для удаления первого дочернего элемента до тех пор, пока не останется ни одного.
person Neelansh Verma    schedule 21.05.2018
comment
Пожалуйста, объясните свои строки кода, чтобы другие пользователи могли понять его функции. Спасибо! - person Ignacio Ara; 21.05.2018
comment
@IgnacioAra Готово! - person Neelansh Verma; 21.05.2018

Просто увидел, как кто-то упомянул этот вопрос в другом, и подумал, что добавлю метод, которого еще не видел:

function clear(el) {
    el.parentNode.replaceChild(el.cloneNode(false), el);
}

var myNode = document.getElementById("foo");
clear(myNode);

Функция clear берет элемент и использует родительский узел для замены себя копией без его дочерних элементов. Небольшой выигрыш в производительности, если элемент является разреженным, но когда у элемента есть группа узлов, выигрыш в производительности достигается.

person Harry Chilinguerian    schedule 14.11.2018
comment
На самом деле кажется, что здесь упоминалось stackoverflow.com/a/15441725/576767 - person Félix Adriyel Gagnon-Grenier; 16.11.2018
comment
Феликс. Должно быть, я это пропустил, спасибо за исправление +1. - person Harry Chilinguerian; 19.11.2018

Функциональный подход:

const domChildren = (el) => Array.from(el.childNodes)
const domRemove = (el) => el.parentNode.removeChild(el)
const domEmpty = (el) => domChildren(el).map(domRemove)

«childNodes» в domChildren предоставит nodeList непосредственных дочерних элементов, который будет пустым, если ни один из них не найден. Чтобы отобразить nodeList, domChildren преобразует его в массив. domEmpty отображает функцию domRemove на все элементы, которые ее удаляют.

Пример использования:

domEmpty(document.body)

удаляет всех дочерних элементов из элемента body.

person Dolph Roger    schedule 10.12.2019

Вы можете удалить все дочерние элементы из контейнера, как показано ниже:

function emptyDom(selector){
 const elem = document.querySelector(selector);
 if(elem) elem.innerHTML = "";
}

Теперь вы можете вызвать функцию и передать селектор, как показано ниже:

Если элемент имеет id = foo

emptyDom('#foo');

Если элемент имеет class = foo

emptyDom('.foo');

если у элемента есть tag = ‹div

emptyDom('div')
person harish kumar    schedule 11.07.2020

element.innerHTML = "" (или .textContent) - безусловно самое быстрое решение

Большинство ответов здесь основаны на ошибочных тестах.

Например: https://jsperf.com/innerhtml-vs-removechild/15.
Этот тест не добавляет новых дочерних элементов к элементу между каждой итерацией. Первая итерация удалит содержимое элемента, а каждая вторая итерация ничего не сделает. В этом случае while (box.lastChild) box.removeChild(box.lastChild) был быстрее, потому что box.lastChild был null в 99% случаев

Вот подходящий тест: https://jsperf.com/innerhtml-conspiracy

Наконец, не используйте node.parentNode.replaceChild(node.cloneNode(false), node). Это заменит узел своей копией без его дочерних элементов. Однако это не сохраняет прослушиватели событий и прерывает любые другие ссылки на узел.

person 12Me21    schedule 05.08.2020

Если вы хотите очистить родительский элемент DOM целиком, это очень просто ...

Просто используйте .empty()

function removeAll() {
  $('#parent').empty();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="removeAll()">Remove all the element of parent</button>
<div id="parent">
  <h3>Title</h3>
  <p>Child 1</p>
  <p>Child 2</p>
  <p>Child 3</p>
</div>

person Rohit Tagadiya    schedule 22.04.2021

просто только IE:

parentElement.removeNode(true);

true - означает глубокое удаление - это означает, что все дочерние элементы также удаляются

person user2656596    schedule 15.12.2016
comment
IE? Это 21 век! - person everlasto; 29.11.2017

Самый простой способ:

let container = document.getElementById("containerId");
container.innerHTML = "";
person milosz    schedule 05.02.2018
comment
Пока это работает, помните, что container.innerHTML = null заставит Internet Explorer отображать текст null. Я бы сказал, что это не совсем удаляет детей. - person Arjan; 26.03.2018

простое и быстрое использование цикла for !!

var myNode = document.getElementById("foo");

    for(var i = myNode.childNodes.length - 1; i >= 0; --i) {
      myNode.removeChild(myNode.childNodes[i]);
    }

это не будет работать в теге <span>!

person Mohit Karkar    schedule 18.08.2018
comment
в приведенном выше решении никакой код не удаляет тег <span> - person Mohit Karkar; 18.08.2018

Другие способы в jQuery

var foo = $("#foo");
foo.children().remove();
//or
$("*", foo ).remove();
//or
foo.html("");
//or
foo.empty();
person Anoop    schedule 16.10.2011
comment
Голосование против, потому что OP сказал, что ответы в прямом DOM предпочтительнее. - person bwindels; 01.06.2015
comment
Кроме того, в jQuery есть .empty() метод, достаточно $("#foo").empty() - person YakovL; 06.08.2018

Если вы хотите что-то вернуть в этот div, innerHTML, вероятно, лучше.

Мой пример:

<ul><div id="result"></div></ul>

<script>
  function displayHTML(result){
    var movieLink = document.createElement("li");
    var t = document.createTextNode(result.Title);
    movieLink.appendChild(t);
    outputDiv.appendChild(movieLink);
  }
</script>

Если я использую метод .firstChild или .lastChild, функция displayHTML() не будет работать после этого, но никаких проблем с методом .innerHTML.

person Bjathr    schedule 18.10.2017

Это чистый javascript, я не использую jQuery, но работает во всех браузерах, даже в IE, и это очень просто для понимания.

   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

   document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i] 
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})
person Ir Calif    schedule 30.03.2017

с jQuery:

$("#foo").find("*").remove();
person Arnaud F.    schedule 17.10.2010
comment
$('#foo').children().remove() намного логичнее - person Krzysztof Dąbrowski; 08.03.2017

person    schedule
comment
Это говорит само за себя - person Alien; 09.05.2020