Получение текста внутри элемента без исключений

Я вижу, что jQuery имеет функцию .text() для получения всего текста внутри элемента и его дочерних элементов.

Есть ли способ получить текст, непосредственно находящийся внутри элемента?

например.

<div>
Here is <b>some</b> text.
</div>

Из этого я хотел бы получить только Here is text.

Ответ 1

var result = $('div').contents().map(function() {
    if( this.nodeType === 3 ) {
        return this.data;
    }
}).get().join('');

Пример: http://jsfiddle.net/PeXue/

Это использует метод contents() [docs], чтобы получить всех детей из div, включая текстовые узлы, затем map() [docs], чтобы создать коллекцию текстового содержимого только текстовых узлов (this.nodeType === 3), используя их свойство .data.

После этого он создает массив из коллекции с помощью get() [docs] и, наконец, присоединяется к результату, используя .join() [docs].

Конечно, ваш селектор должен быть специфичным для таргетинга <div>.


РЕДАКТИРОВАТЬ: Если вы хотите нормализовать пробелы между словами немного, вы можете обрезать ведущее и конечное белое пространство из содержимого каждого текста node с помощью jQuery.trim() [docs], затем дайте .join() одно пространство для присоединения к каждому набору.

var result = $('div').contents().map(function() {
    if( this.nodeType === 3 ) {
        return $.trim( this.data );
    }
}).get().join(' ');

alert( result );

Пример: http://jsfiddle.net/PeXue/1

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

var result = $('div').contents().map(function() {
    return $.trim( this.data ) || null;
}).get().join(' ');

alert( result );

Пример: http://jsfiddle.net/PeXue/2


ИЗМЕНИТЬ 2:

Вы можете получить огромное увеличение производительности, используя jQuery.map() [docs], который предназначен для более общего использования.

var result = $.map( $('div')[0].childNodes, function(val,i) {
  if (val.nodeType === 3) {
    return val.data;
  }
}).join('');

Вот тест производительности, показывающий разницу.

Ответ 2

Рабочий пример в jsFiddle

var divClone = $('div').clone();    //  WARNING:
divClone.children().remove();       //  This code is much slower than the 
alert(divClone.text());             //  code in the selected answer.

Update

Тест производительности в ответе @patrick dw ясно показывает, что его подход - лучшая альтернатива. Я не удалял этот ответ, потому что, по-моему, полезно будущим читателям вопроса, который может не знать, какой путь лучше.