Обратные вызовы в JQuery / JavaScript - PullRequest
1 голос
/ 17 января 2012

Я пытался привязать событие при нажатии к таблице tr в JQuery.Первый пример, приведенный ниже, сработал, как и ожидалось, а второй - нет.Функция populate_form сработала, не дожидаясь события.

Мне было интересно, может ли кто-нибудь объяснить мне, почему?

Заранее спасибо ..

Пример первый

.click(function() { populate_form(row.name, row.age, row.dob); });

Пример второй

.click(populate_form(row.name, row.age, row.dob));

Ответы [ 4 ]

4 голосов
/ 17 января 2012

Быстрый ответ, который, вероятно, будет уже дан ответ и принят ко времени публикации Этот ответ заключается в том, что ваша вторая версия вызывает populate_form, а затем передает результат функцию , чтобы щелкнуть. Что, в данном случае, не то, что вы хотите. Что .click() действительно ожидает ссылка на функцию для выполнения, когда что-то вызывает это событие.

Это быстрый ответ; что может иметь или не иметь смысла сразу. Итак, давайте посмотрим
надумал простой пример. Рассмотрим следующий код:

var Foo = function() {
    var noop = function() { };
    this.callback = noop;
}

Foo.prototype.setCallback = function(callback) {
    this.callback = callback;
}

Foo.prototype.go = function() {
    this.callback.apply(this);
}

Это грубое чрезмерное упрощение того, что делает jQuery, но оно все понимает. У нас есть маленький класс, и у него есть два метода: setCallback и go. Теперь идея что когда мы вызываем go(), мы хотим выполнить любую функцию, которую мы предоставили. Также обратите внимание, что по умолчанию callback устанавливается на пустую функцию (или noop).

Итак, если мы сделаем это:

var bar = new Foo();
bar.go()

Тогда ничего не произойдет, но мы не получим никаких ошибок. Это потому, что вызывается пустая функция noop.

Теперь поговорим о двух способах определения функции в JavaScript: Выражение функции и объявление функции.

Объявление функции выглядит так:

function sayHelloDeclaration() {
    alert("Hello from a declaration!");
}

И если бы мы хотели вызвать эту функцию, мы бы написали:

sayHelloDeclaration();

И мы бы увидели предупреждение. Однако, если бы мы просто хотели сослаться на саму функцию (не вызывая ее), мы бы просто использовали ее имя:

sayHelloDeclaration;

Обратите внимание на отсутствие скобок; это делает это просто ссылкой на функцию. Никогда не велели выполнять свою работу, поэтому предупреждение никогда не появляется. Теперь давайте вернемся к нашему классу Foo, а конкретнее к функции setCallback:

Foo.prototype.setCallback = function(callback) {
    this.callback = callback;
}

Обратите внимание, что этот метод принимает один аргумент и присваивает его свойству this. По сути, мы хотим сохранить ссылку на функцию для последующего использования. И давайте посмотрим на метод go:

Foo.prototype.go = function() {
    this.callback.apply(this);
}

Это берет все, что хранится в this.callback и пытается вызвать его, используя, .apply(), мы могли бы также использовать .call() (тонкая разница между этими двумя). Или просто сказал бы this.callback().

Итак, давайте посмотрим, как это будет использоваться. Если бы я написал ...

function sayHelloDeclaration() {
    alert("Hello from a declaration!");
}

var bar = new Foo();
bar.setCallback(sayHelloDeclaration);

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

function sayHelloDeclaration() {
    alert("Hello from a declaration!");
}

var bar = new Foo();
bar.setCallback(sayHelloDeclaration);
bar.go();

... вы увидите всплывающее окно. Это потому, что go() вызвал ссылку на sayHello, которую он отслеживал. Тем не менее, ваш второй пример делает что-то вроде этого:

function sayHello() {
    alert("Hello from a declaration!");
}

var bar = new Foo();
bar.setCallback(sayHelloDeclaration());

Обратите внимание, что вы получаете всплывающее окно, однако мы никогда не звонили bar.go(). Это потому, что sayHello() вызывает метод. Возвращаемое значение из этой функции передается в setCallback. Если бы мы попытались позвонить bar.go(), мы бы получили ошибка типа, потому что мы попытались установить callback на что-то, что не было функцией, а затем попытались вызвать ее. Это "плохая вещь".


А как насчет выражений функций? Выражение функции - это другой способ определения функции. В некотором роде вы можете определить строку или число в JavaScript. Имеет похожую, но немного иную форму:

var sayHelloExpression = function() { alert("Hello from expression"); };

По сути, это создает новую анонимную функцию и присваивает ее переменной sayHelloExpression. Таким образом, мы можем использовать его так же, как в предыдущем примере:

var bar = new Foo();
bar.setCallback(sayHelloExpression);
bar.go();

Или мы могли бы пропустить присвоение этой переменной все вместе и просто сказать:

var bar = new Foo();
bar.setCallback(function() { alert("Hello from expression"); });
bar.go();

Теперь есть некоторые тонкие (но важные) различия между объявлениями функций и выражениями функций, о которых другие люди узнали более подробно, но здесь необходимо понять, что вы можете говорить о функции, не вызывая ее. Вы также можете отслеживать ссылку на функцию, а затем вызывать ее позже.

В первом случае вы создаете выражение функции, которое вызывает другую функцию с некоторыми аргументами.Так же, как наш alert в нашем выражении функции, за исключением того, что это определенная пользователем функция.Но то, что вы даете setCallback, все еще является ссылкой на функцию , которая не будет вызываться до позже .


Наконец, давайте посмотрим наразумное использование для вызова функции, используемой при работе с обратным вызовом, подобным этому.Примером может служить ситуация, когда у вас есть функция, которая возвращает другую функцию.Рассмотрим эту функцию:

function createGreeter(name) {
    return function() {
        alert("Hello there " + name + "!!")
    }
}

Эта функция принимает один аргумент, а затем создает и возвращает другую функцию.

var sayHiBob = createGreeter("Bob");
sayHiBob();  // alerts "Hello there Bob!!"

Эта функция похожа на небольшую фабрику длянам создавать другие функции с.В этом случае имеет смысл использовать эту функцию при ее использовании с нашим методом setCallback, потому что мы хотим установить обратный вызов для результата функции, котораямы призываем.Примерно так.

var bar = new Foo();
bar.setCallback(createGreeter("Joe"));
bar.go(); // alerts "Hello there Joe!!"

Есть еще много всего, чему можно научиться, но это мой длинный ответ на этот вопрос.

1 голос
/ 17 января 2012

Во второй версии вы выполнили функцию напрямую.Javascript не имеет конкретного понимания .click и, следовательно, рассматривает его как любой другой вызов функции.Он обрабатывает его не иначе, чем

.anyName(populate_form(...))

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

.anyName(function() { populate_form(...); });
0 голосов
/ 17 января 2012

Вы не можете сделать это так, потому что событие click будет передано функции в качестве параметра.

.click(function(event){....});

Так что, даже если вы даете

.click(populate_form);

функция populate_form будет вызываться с событием в качестве параметра. Таким образом, результат будет

populate_form(event);

Так что правильный путь - ваш Пример Один

.click(function(event) { populate_form(row.name, row.age, row.dob); });
0 голосов
/ 17 января 2012

jquery нужна либо ссылка на функцию, либо на саму функцию, которую нельзя передать прямым кодом.так что либо:

.click(function(){....});

или

.click(populate_form);
...