Chrome / jQuery Uncaught RangeError: Максимальний розмір стека викликів перевищений


113

Я отримую помилку "Uncaught RangeError: Максимальний розмір стека викликів перевищено" на chrome. ось моя функція jQuery

$('td').click(function () {
        if ($(this).context.id != null && $(this).context.id != '') {
            foo($('#docId').val(), $(this).attr('id'));
        }
        return false;
    });

Зауважте, що на сторінці є десятки тисяч комірок. Однак я зазвичай асоціюю переповнення стека з рекурсією, і в цьому випадку, наскільки я бачу, його немає.

Чи створює подібний лямбда автоматично генерує набір речей на стек? чи є якийсь спосіб його обійти?

На даний момент єдине рішення, яке я маю, - це генерувати події onclick явно в кожній комірці під час надання HTML, що робить HTML значно більшим.


2
Ви впевнені, що функція foo не повторюється? Чи все-таки трапляється помилка, якщо ви видалите цей виклик функції?
sth

1
Чи працює це так, як очікувалося в інших браузерах? Чи виникає ця помилка, коли коментуєте foo($('#docId').val(), $(this).attr('id'));рядок? - Порада щодо додаткової продуктивності: кешуйте результати селекторів - наприклад, зберігайте результат $(this)у змінній і тоді використовуйте їх у вашому оброблювачі за потребою.
WTK

У мене є аналогічна проблема, але потрібні події в миші. Під час використання тіла або таблиці я не отримую достатньо подій.
ericslaw

Відповіді:


133

Оскільки "на сторінці є десятки тисяч комірок", прив'язка події клацання до кожної клітинки спричинить жахливу проблему з продуктивністю. Існує кращий спосіб зробити це - прив’язати подію кліку до тіла, а потім з’ясувати, чи елемент клітини був ціллю клацання. Подобається це:

$('body').click(function(e){
       var Elem = e.target;
       if (Elem.nodeName=='td'){
           //.... your business goes here....
           // remember to replace $(this) with $(Elem)
       }
})

Цей метод не лише виконає ваше завдання з нативним тегом "td", але і з доданим пізніше "td". Я думаю, вам буде цікава ця стаття про прив'язку та делегат подій


Або ви можете просто використовувати метод " .on () " jQuery з тим же ефектом:

$('body').on('click', 'td', function(){
        ...
});

дякую, ми все одно боремося за ефективність, тому це відмінна ідея :-)
Енді

60
Nooo, не використовуйте .live () !!! bitovi.com/blog/2011/04/… Використовуйте .delegate () (або .on (), якщо ваш jQuery досить новий), і делегуйте на рівні таблиці, а не на весь документ. Це значно покращить вашу ефективність, ніж просто використання .live (), який по суті буде просто делегувати весь документ вниз.
брендова вафля

19
І .live видалено з jQuery 1.9
cpuguy83

37

Ви також можете отримати цю помилку, коли у вас є нескінченний цикл. Переконайтеся, що у вас немає постійних, рекурсивних посилань на себе.


6
Це вирішило моє питання. У мене були і в <a id="linkDrink" onclick="drinkBeer();">Drink</a>, і $('#linkDrink').click();в drinkBeer().
Aycan Yaşıt

7

Моя була більше помилкою, що сталося - це натискання циклу (я думаю), в основному, натиснувши на логін, також було натиснуто батьків, що призвело до перевищення максимального розміру стека викликів.

$('.clickhere').click(function(){
   $('.login').click();
});

<li class="clickhere">
  <a href="#" class="login">login</a>
</li>

3

Ця проблема трапилася зі мною, коли я використовував jQUery Fancybox всередині веб-сайту з багатьма іншими плагінами jQuery. Коли я використовував LightBox ( сайт тут ) замість Fancybox, проблеми вже немає.


1

Ви можете використовувати

  $(document).on('click','p.class',function(e){
   e.preventDefault();
      //Code 
   });

0

Нещодавно я також натрапив на це питання. У діалоговому розділі у мене була дуже велика таблиця. Це було> 15000 рядів. Коли у діалоговому вікні дзвонили .empty (), я отримував помилку вище.

Я знайшов рішення навколо, де перед тим, як зателефонувати в очищенні діалогового вікна, я видаляв би кожен інший рядок із дуже великої таблиці, а потім зателефонував у .empty (). Здавалося, він працював, хоча. Здається, моя стара версія JQuery не може обробити такі великі елементи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.