Объекты jQuery() могут содержать объекты не-DOM?

100
7

Анализируя код, показанный этим вопросом SO, я просто заметил способ использования jQuery для итерации массива JSON:


$(data).each(function() {

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


$.each(data, function() {

В самом деле, в справочной странице jQuery.each() указано:


Функция $.each() не совпадает с $(selector).each(), которая используется исключительно для итерации над объектом jQuery.



Но поскольку OP, казалось, имел свой код, по крайней мере частично работающий, мне было любопытно протестировать, и он обнаружил, что он работает!

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


var data = [
{"key": "value-1"},
{"key": "value-2"},
{"key": "value-3"}
];

$(data).each(function() {
document.write('<br />' + this.key);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Итак, если $(data).each() работает, когда data является массивом JSON, это означает, что этот массив является приемлемым контентом для $(data) для возврата объекта jQuery.


Затем, проведя исследование, я проверил справочную страницу jQuery (elementArray) и просмотрел раздел jQuery( elementArray ), в котором говорится:


elementArray
Тип: массив
Массив , содержащий набор элементов DOM, чтобы обернуть объект jQuery.



Согласно вышеизложенному, массив объектов (вместо элементов DOM) должен завершиться неудачей.

Поэтому я тестировал сравнение объектов, возвращаемых либо этим $(data), либо простым $('body'). Вот результат:


var data = [
{"key": "value-1"},
{"key": "value-2"},
{"key": "value-3"}
];

function log(obj, init) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var $row = $('tr[data-prop=' + prop + ']');
if (!$row.length) {
$row =
$('<tr data-prop="' + prop + '"><th>' + prop + '</th></tr>')
.appendTo($('table'));
if (!init) {
$row.append('<td></td>');
}
}
$row.append('<td>' + JSON.stringify(obj[prop]).substr(0,25) + '</td>');
}
}
}

log($('body'), true);
log($(data), false);


table {
border-collapse: collapse;
border: 1px solid #000;
}
th, td {
border: 1px solid #000;
padding: 5px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<th>Property</th>
<th>$('body')</th>
<th>$(data)</th>
</tr>
</table>

На самом деле кажется, что все можно преобразовать в объект jQuery.

Я озадачен: я изобретаю колесо!?

спросил(а) 2016-03-17T04:13:00+03:00 4 года, 3 месяца назад
1
Решение
55

Да, конструктор jQuery принимает массив, и вы можете выполнять итерацию через возвращенную коллекцию jQuery с помощью метода $.fn.each и this в обработчике относится к каждому элементу. Коллекция jQuery представляет собой array-like объект.


Но, нет, это не означает, что вы можете успешно вызвать все связанные с DOM методы в коллекции. Просто попробуйте $(data).html() в качестве примера, и вы получите сообщение об ошибке, поскольку оно ожидает увидеть DOM node, а не простой объект или строку в коллекции.


В качестве другого примера попробуйте $(['foo']).text() и он выкинет ошибку Uncaught RangeError: Maximum call stack size exceeded в jQuery 2.2.2.

И теперь попробуйте:


/**
* `text` reads textContent of DOM elements (nodeType = 1)
* and `nodeValue` of textNodes (nodeType = 3)
* and returns the concatenated text
*/
$([
{ "nodeType": 1, "textContent": "value-1" },
{ "nodeType": 3, "nodeValue": "value-2" },
{ "textContent": "I'm a rebel" }
]).text()

и он возвращает "value-1value-2"!

ответил(а) 2016-07-10T12:39:00+03:00 3 года, 11 месяцев назад
53

Вы слишком много читаете в документации.


Да, обычно jQuery(elementArray) будет использоваться в массиве элементов. Но это может быть массив чего угодно.

Цель состоит в том, чтобы использовать $.each() и, возможно, другие удобные методы для массивов с обычными элементами. Вы обнаружите, что другие методы jQuery не будут соответствовать чему-либо в вашем массиве, если ваш массив не имеет каких-либо элементов.

ответил(а) 2016-07-10T09:26:00+03:00 3 года, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема