2017-11-25 200 views
3

我試圖得到callback functions的掛鉤,但我遇到了一些我不完全瞭解的東西。.filter()如何使回調函數調用另一個函數?

這段代碼在下面的例子中使用時效果很好。

zombieCreatures = creatures.filter(filterCreatures); 

不幸的是,這個代碼塊在同一個例子中不起作用。

zombieCreatures = creatures.filter(function(v) { 
    filterCreatures(v); 
}); 

對我來說,他們看起來像相同的指令,但顯然我不正確。有什麼不同? .filter()之內是否有可能使回調函數調用另一個函數?

'use strict'; 
 

 
var creatures = [], zombieCreatures = []; 
 

 
var filterCreatures; 
 

 
creatures = [ 
 
    {species: 'Zombie', hitPoints: 90}, 
 
    {species: 'Orc', hitPoints: 40}, 
 
    {species: 'Skeleton', hitPoints: 15}, 
 
    {species: 'Zombie', hitPoints: 85} 
 
]; 
 
\t 
 
filterCreatures = function(v) { 
 
    return v.species === 'Zombie'; 
 
} 
 
\t 
 
zombieCreatures = creatures.filter(function(v) { 
 
    filterCreatures(v); 
 
}); 
 

 
console.log(zombieCreatures);

回答

4

是的,你當然可以叫filter回調內部的任何其他功能。

你唯一缺少的是回調需要返回的值。您的回撥沒有return聲明。它調用filterCreatures()函數,但它會丟棄該函數返回的值,默認返回undefined

比較與您的代碼的原始版本:

creatures.filter(filterCreatures); 

在這段代碼,filter()直接調用filterCreatures功能,然後使用它的返回值來決定是否要包括的元素。您在代碼中沒有明確地看到這一點,但filter()正在尋找該返回值。

下面是一個練習,以幫助澄清這一點。取出您的破解代碼並將內聯過濾器回調移出到指定函數。我們將其稱爲filterCreaturesWrapper。因此,而不是這樣的:

filterCreatures = function(v) { 
    return v.species === 'Zombie'; 
} 

zombieCreatures = creatures.filter(function(v) { 
    filterCreatures(v); 
}); 

,我們有這樣的:

filterCreatures = function(v) { 
    return v.species === 'Zombie'; 
} 

filterCreaturesWrapper = function(v) { 
    filterCreatures(v); 
} 

zombieCreatures = creatures.filter(filterCreaturesWrapper); 

如果你學習,你會看到它像以前一樣是完全相同的代碼,我們剛剛搬到這附近有一座小。 filterCreaturesWrapper與在.filter()調用中內聯的功能相同。現在問題應該跳出來,我們:filterCreatures有一個return聲明和filterCreaturesWrapper沒有。

再回到原來的斷碼,這是因爲如果我們寫:

zombieCreatures = creatures.filter(function(v) { 
    filterCreatures(v); 
    return undefined; // .filter treats this as 'false' 
}); 

因此,只要在你的回調添加return和它的作品:

'use strict'; 
 

 
var creatures = [], zombieCreatures = []; 
 

 
var filterCreatures; 
 

 
creatures = [ 
 
    {species: 'Zombie', hitPoints: 90}, 
 
    {species: 'Orc', hitPoints: 40}, 
 
    {species: 'Skeleton', hitPoints: 15}, 
 
    {species: 'Zombie', hitPoints: 85} 
 
]; 
 
\t 
 
filterCreatures = function(v) { 
 
    return v.species === 'Zombie'; 
 
} 
 
\t 
 
zombieCreatures = creatures.filter(function(v) { 
 
    return filterCreatures(v); // <-- added "return" 
 
}); 
 

 
console.log(zombieCreatures);

並非所有的語言都是這樣的。例如,Ruby無論是否明確說明return,都會返回方法(函數)中的最後一個表達式。所以,如果你正在編寫Ruby代碼(假設所有其他位都轉換爲Ruby),那麼你的代碼就可以工作了!

+0

非常感謝你,我拉着我的頭髮!我從來沒有想過使用'return'。我要閱讀'return'。我把那一個擰得比我想要承認的要多。 – DR01D

1

filter將調用它爲數組中的每個項目提供的函數。它會檢查每個項目的該函數的返回值,如果返回值爲真,它會將該項目添加到新數組中。

換句話說,它返回一個回調函數返回一個真值的所有項的數組。

在第一個示例中,您直接傳遞filterCreatures函數,當生物爲殭屍時返回true

在第二個例子中,你傳遞的另一個功能和呼叫filterCreatures內部,但不返回任何東西的意思傳遞給篩選每一個項目,這是falsy沒有東西回報過濾的undefined回調。

對於它的工作,你必須返回調用filterCreatures的結果:

zombieCreatures = creatures.filter(function(v) { 
    return filterCreatures(v); 
}); 

話雖這麼說,周圍filterCreatures附加功能沒有太多使用時filterCreatures本身並沒有你所需要的一切。