JavaScript: изменение значения onclick с или без jQuery

Ваше нулевое завершение в конце списка аргументов передается вашей функции как int (32-битное) значение, но ваш va_arg вытягивает значение NSInteger (он же long) из стека. Таким образом, вы извлекаете дополнительные 32 бита из стека и смотрите на все это как на одно 64-битное значение, половина которого - это ноль, который вы намеревались, а половина - то, что произошло рядом с ним в памяти. в то время.

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

[var test:Enum1, Enum2, Enum3, Enum4, Enum5, Enum6, (NSInteger)0];

Как поясняет Роб Мейофф в комментариях ниже, литерал с нулевым нулем, являющийся целочисленным значением, рассматривается как [115 ]. Применяются обычные целочисленные правила продвижения C *; в списке varargs, поскольку аргументы не имеют объявленного типа, более целочисленные типы повышаются до - и передаются как - int с. Поскольку компилятор не имеет представления о фактических типах, которые вы ожидаете увидеть во время выполнения, этот int не будет повышен до long для вас, поэтому он попадает в стек как int.

Как правило, завершение varargs выполняется либо неявно (предвидение стиля printf числа и типов arg), либо с константой, подобной nil, которая будет правильной ширины, и эти подходы позволяют избежать этой проблемы. В старом 32-битном мире, где значения enum были int с, и NSInteger были int, и целочисленное продвижение по умолчанию было , также - int, эти различия были скрыты.

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

* См. Стандарт C18 §6.3.1.1 ;-)


Объяснитель бонуса: почему вы увидели значение enum == 4294967296?

[1133 ] Десятичное число 4294967296 равно 0x0000000100000000. Вторая (нижняя) половина этого значения была 32-битным нулем, который вы поставили туда. Верхняя половина выглядит так, как будто это просто число 1. Сначала я предполагал, что это будет какая-то другая (действительная) часть текущего стекового фрейма, но некоторые исследования (на 64-битном Mac, использующем текущий llvm с Xcode и т. Д.) Показывают, что компилятор устанавливает вызов -test:... путем нажатия на enum args с помощью movq (move quad = 64bit) и конечного нулевого arg с movl (move long = 32bit). Поскольку стек выровнен на 64 бита, в стеке памяти между предпоследним и конечным аргументами остается «дыра» в 32 бита (т.е. не перезаписывается). Это место, которое содержало 0x1. Таким образом, вы не читаете соседний аргумент или другое значение, которое является допустимым, но используется для чего-то другого. Вы читаете призрачное значение из рабочего пространства какого-то более раннего вызова функции. В моей отладке это не похоже на alloc / init из Variable - это что-то предшествующее и не связанное с тестовым кодом под рукой.

48
задан 2 revs, 2 users 100% 5 May 2009 в 19:58
поделиться

7 ответов

Вам больше не следует использовать onClick , если вы используя jQuery. jQuery предоставляет свои собственные методы присоединения и привязки событий. См. .click ()

$(document).ready(function(){
    var js = "alert('B:' + this.id); return false;";
    // create a function from the "js" string
    var newclick = new Function(js);

    // clears onclick then sets click using jQuery
    $("#anchor").attr('onclick', '').click(newclick);
});

. Это должно отменить функцию onClick - и также сохранить ваш «javascript from a string».

Лучше всего будет удалить onclick = "" из элемента в коде HTML и переключитесь на использование ненавязчивого метода для привязки события к щелчку.

Вы также сказал:

Используя onclick = function () {return eval (js); } не работает, потому что вы не можете использовать return в коде, переданном в eval ().

Нет - не будет, но onclick = eval ("(function () {" + js + "})"); перенесет переменную 'js' в оболочку функции. onclick = new Function (js); также работает и немного чище для чтения. (обратите внимание на заглавную F) - см. документацию по конструкторам Function ()

74
ответ дан 26 November 2019 в 18:54
поделиться

просто используйте метод привязки jQuery! Jquery-selector ! .bind ('event',! fn!);

Подробнее о событиях в jQuery смотрите здесь

0
ответ дан 26 November 2019 в 18:54
поделиться

Одна хитрость с Jquery заключается в том, что функция щелчка не распознает нажатие, закодированное вручную, из html.

Итак, вам в значительной степени придется выбирать. Установите все ваши обработчики в функции init или все они в html.

Событием click в JQuery является функция щелчка $ ("myelt"). Click (function ....).

0
ответ дан 26 November 2019 в 18:54
поделиться

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

<a id="the_anchor" href="">

А затем, чтобы назначить вашу строку JavaScript для onclick привязки, поместите это где-нибудь в другом месте (то есть в заголовок, позже в теле, что угодно):

<script>
    var js = "alert('I am your string of JavaScript');"; // js is your string of script
    document.getElementById('the_anchor').href = 'javascript:' + js;
</script>

Если у вас есть вся эта информация на сервере перед отправкой страницы, вы также можете просто поместить JavaScript прямо в атрибут href привязки, например:

<a href="javascript:alert('I am your script.'); alert('So am I.');">Click me</a>
0
ответ дан 26 November 2019 в 18:54
поделиться

Придумал быстрое и грязное решение этой проблемы. Только что использовано

Hope это помогает

-3
ответ дан 26 November 2019 в 18:54
поделиться

Кстати, без JQuery это тоже можно было бы сделать, но, очевидно, это довольно некрасиво, поскольку рассматривается только IE / не-IE:

if(isie)
   tmpobject.setAttribute('onclick',(new Function(tmp.nextSibling.getAttributeNode('onclick').value)));
else
   $(tmpobject).attr('onclick',tmp.nextSibling.attributes[0].value); //this even supposes index

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

3
ответ дан 26 November 2019 в 18:54
поделиться

Note that following gnarf's idea you can also do:

var js = "alert('B:' + this.id); return false;";<br/>
var newclick = eval("(function(){"+js+"});");<br/>
$("a").get(0).onclick = newclick;

That will set the onclick without triggering the event (had the same problem here and it took me some time to find out).

0
ответ дан 26 November 2019 в 18:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: