Транскрипт и Javascript с помощью jQuery

Я хочу перевести этот образец html-документа в Transcrypt:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
    $("p").click(function(){
        $(this).hide();
    });
});
</script>
</head>
<body>

<p>If you click on me, I will disappear.</p>
<p>Click me away!</p>
<p>Click me too!</p>

</body>
</html>

Мой код приводит к hide.py:

__pragma__ ('alias', 'S', '$')

def hide():
    S("p").click(S(this).hide())

S(document).ready(hide)

При запуске hide.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<script src="__javascript__/hide.js" charset="UTF-8"></script> 
<p>If you click on me, I will disappear.</p>
<p>Click me away!</p>
<p>Click me too!</p>
</body>
</html>

Я получаю сообщение об ошибке TypeError: (промежуточное значение).apply не является функцией в окне консоли.


person bunkus    schedule 06.03.2018    source источник


Ответы (1)


В следующей строке:

S("p").click(S(this).hide())

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

Транскрипт и FileReader

Если я это исправлю, я получу:

__pragma__('alias', 'S', '$')

def hide():
   S("p").click(S(this).hide)

S(document).ready(hide)

Он сообщает о нескольких недопустимых ключевых кадрах.

Если я сделаю то же самое непосредственно в JavaScript (то есть без Transcrypt):

function hide () {
   $("p").click($(this).hide);
}

$(document).ready(hide)

Я получаю точно такие же ошибки.

Я посмотрел, какой код JS должен быть здесь:

https://www.w3schools.com/jquery/jquery_hide_show.asp

а именно:

function hide () {
    $("p").click(function () {$(this).hide ()});
}

$(document).ready(hide)

Это действительно то, что находится в вашем исходном встроенном скрипте HTML. В Transcrypt это будет:

__pragma__('alias', 'S', '$')

def hide():
   S("p").click(lambda: S(this).hide ())

S(document).ready(hide)

Я протестировал обе, и версия JavaScript, а также версия Transcrypt работают нормально.

Если я посмотрю на код, который генерирует Transcrypt, это неудивительно:

    var hide = function () {
        $ ('p').click ((function __lambda__ () {
            return $ (this).hide ();
        }));
    };
    $ (document).ready (hide);

Код, сгенерированный Transcrypt, как две капли воды похож на написанный вручную JavaScript.

Пусть вас не смущает тот факт, что здесь используется hide () (с фигурными скобками), а не hide (без фигурных скобок). Здесь обратным вызовом является анонимная лямбда-функция c.q, а не функция hide. И анонимный c.q. Лямбда-функции не вызываются при передаче в click (). Другими словами, они не имеют завершающих фигурных скобок.

Делая ту же ошибку намеренно:

__pragma__('alias', 'S', '$')

def hide():
   S("p").click((lambda: S(this).hide ())())

S(document).ready(hide)

не будет работать, и не будет:

function hide () {
    $("p").click((function () {$(this).hide ()}) ());
}

$(document).ready(hide)

Итак, различие между передачей обратного вызова:

 $("p").click (my_callback)     // Right

и вызывая его:

 $("p").click (my_callback ())  // Wrong

является решающим.

Надеюсь, это немного прояснит ситуацию.

Вы можете задаться вопросом, почему нельзя просто передать $(this).hide без дополнительной функции-оболочки, которая ее вызывает.

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

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

Подсказка по поводу именования функций: вы назвали свою функцию hide, что как бы подпитывает путаницу между вызовом функции и передачей ее адреса. Ваш hide ничего не скрывает. Он устанавливает только обратный вызов, который может что-то скрывать. Так что имя install_hide, вероятно, было бы более подходящим, хотя и немного длиннее...

person Jacques de Hooge    schedule 06.03.2018
comment
Большое спасибо за подробный ответ. Это также отвечает на вопрос об анонимных функциях в Javascript и о том, как это можно перевести на Python с помощью лямбда-выражения. Очень хороший намек. - person bunkus; 07.03.2018