簡體   English   中英

JQuery / JavaScript中的回調

[英]Callbacks in JQuery / JavaScript

我試圖將on click事件綁定到JQuery中的表tr。 下面的第一個示例按預期工作,但是第二個則沒有。 在不等待事件的情況下觸發populate_form函數。

我想知道是否有人可以向我解釋原因?

提前致謝..

例子一

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

例子二

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

我在發布此答案時可能已經回答並接受了快速答案,即您的第二個版本調用populate_form ,然后將函數結果傳遞給click。 在這種情況下,這不是您想要的。 當某些事件觸發該事件時, .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正在執行的操作的過度簡化 ,但它可以使您理解。 我們有一個小類,它有兩個方法: setCallbackgo 現在的想法是,當我們調用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的仍然是對一個函數的引用,直到以后才會調用。


最后,讓我們看一下在處​​理這樣的回調時調用use函數的合理用法。 例如,當您有一個函數返回另一個函數時。 考慮以下功能:

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!!"

還有很多東西要學習,但這是我對這個問題的長期回答。

在第二個版本中,您直接執行了該函數。 Javascript對.click沒有任何特殊的了解,因此將其像對待其他函數調用一樣對待。 它對待與

.anyName(populate_form(...))

在這兩種情況下,它都會立即執行函數populate_from並將結果傳遞給方法。 為了將其建立為回調,您需要將其顯式包裝在一個函數中,然后將其值傳遞給該方法

.anyName(function() { populate_form(...); });

jQuery需要一個對函數的引用,或者對函數本身的引用,您不能直接輸入代碼。 所以:

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

要么

.click(populate_form);

您不能那樣做,因為click事件將作為參數傳遞給函數。

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

所以即使你給

.click(populate_form);

函數populate_form將以事件為參數被調用。 因此結果將是

populate_form(event);

所以正確的方法是您的示例一

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM