var?fs = require(‘fs‘);
var?files =【‘a . txt’,‘b . txt’,‘c . txt’】;
為了什麽?(var?I = 0;我& ltfiles.lengthi++) {
fs . readfile(files【I】,‘utf-8‘,?功能?(呃,內容){
console.log(文件【I】+‘:‘+內容);
});
}
這段代碼的功能很直觀,就是依次讀取文件?a.txt、b.txt?、c.txt?,並輸出文件名和內容。假設這三個文件的內容是?AAA?、BBB?然後呢。CCC,那麽預期的輸出結果是:
a.txt: AAA
b站:BBB
c.txt: CCC
但是運行這段代碼的結果是什麽呢?結果是這樣的:
未定義:AAA
未定義:BBB
未定義:CCC
這個結果表明文件的內容輸出正確,但文件名是錯誤的,這意味著,contents?結果是正確的,但是?文件【I】?的價值是什麽?未定義。怎麽可能讀取文件名不正確的文件的內容呢?既然很難直觀理解,那我們把?文件【I】?分解後打印出來,在讀取文件的回調函數中單獨輸出?文件、我?然後呢。文件【I】?。
var?fs = require(‘fs‘);
var?files =【‘a . txt’,‘b . txt’,‘c . txt’】;
為了什麽?(var?I = 0;我& ltfiles.lengthi++) {
fs . readfile(files【I】,‘utf-8‘,?功能?(呃,內容){
console.log(文件);
console . log(I);
console.log(文件【I】);
});
}
運行修改後的代碼,結果如下:
【a.txt,b.txt,c.txt】
三
不明確的
【a.txt,b.txt,c.txt】
三
不明確的
【a.txt,b.txt,c.txt】
三
不明確的
看到這裏是不是有點啟發呢?三倍產出?我?是所有的值嗎?3?,超越?文件?數組的下標範圍。文件【I】?的價值是什麽?未定義?是的。這種情況通常發生在?為了什麽?發生在循環結束時,例如?for(var I = 0;我& ltfiles.lengthI++),退出循環時?我?的值是files.length?的價值。從什麽時候開始?我?的價值是什麽?3?這意味著事實上。fs.readFile?在的回調函數中?我?這些值都在循環退出後,因此無法區分。然後呢。文件【I】?作為什麽?fs.readFile?的第壹個參數在循環中傳遞,因此可以定位文件並顯示文件的內容。
現在問題很清楚了:原因是3?第二個讀取文件的回調函數實際上是同壹個實例,指的是?我?該值是執行上述循環後的值,因此無法區分。如何解決這個問題?我們可以使用
JavaScript?函數式編程的特點是,手動創建閉包:
//forloopclosure.js
var?fs = require(‘fs‘);
var?files =【‘a . txt’,‘b . txt’,‘c . txt’】;
為了什麽?(var?I = 0;我& ltfiles.lengthi++) {
(功能?㈠{
fs . readfile(files【I】,‘utf-8‘,?功能?(呃,內容){
console.log(文件【I】+‘:‘+內容);
});
})(I);
}
上面的代碼在哪裏?為了什麽?在循環體中建立壹個匿名函數,循環叠代變量?我?作為函數的參數傳遞並調用。由於運行時閉包的存在,匿名函數中定義的變量(包括參數表)都在其內部函數(fs.readFile?的回調函數在執行完成後才會釋放,那麽我們在其中訪問什麽呢?我?它們是不同的閉包實例,在循環體執行期間創建並保留不同的值。
補充:closure的寫入方式無法保證按照數組中存儲文件的順序讀取文件內容,相當多的文件讀取操作是並行進行的,讀取速度根據文件大小而定;ForEach可以保證順序讀取;
事實上,這種編寫方法並不常見,因為它降低了程序的可讀性,所以不建議使用。在大多數情況下,我們可以使用數組。forEach?解決這個問題的方法:
//callbackforeach.js
var?fs = require(‘fs‘);
var?files =【‘a . txt’,‘b . txt’,‘c . txt’】;
files.forEach(函數?(文件名){
fs.readFile(文件名,‘utf-8‘,?功能?(呃,內容){
console.log(文件名+‘:‘+內容);
});
});