var?fs = require(' fs ');
var?files = ['a.txt ',' b.txt ',' c . txt '];
為了什麽?(var?I = 0;我& ltfiles.lengthi++) {
fs.readFile(文件[i],' utf-8 ',?功能?(錯誤,內容){
console.log(文件[i] + ': ' +內容);
});
}
這段代碼的作用很直觀,就是依次讀取文件?a.txt、b.txt?、c.txt?,並輸出文件名和內容。假設這三個文件的內容是?AAA?、BBB?然後呢。CCC,那麽預期的輸出結果是:
a.txt: AAA
b.txt: BBB
c . txt:cc
但是運行這段代碼的結果是什麽呢?原來是這樣的結果:
未定義: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(文件[i],' utf-8 ',?功能?(錯誤,內容){
console.log(文件);
console.log(壹);
console . log(files[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(文件[i],' utf-8 ',?功能?(錯誤,內容){
console.log(文件[i] + ': ' +內容);
});
})(壹);
}
上面的代碼在哪裏?為了什麽?在循環體內建立匿名函數,循環叠代變量?我?作為函數的參數傳遞並被調用。由於運行時閉包的存在,匿名函數中定義的變量(包括參數表)在其內部函數(fs.readFile?的回調函數直到執行完成才會釋放,那麽我們在裏面訪問什麽呢?我?它們是不同的閉包實例,在循環體執行期間創建,並保留不同的值。
補充:閉包的寫入方式不能保證按照文件在數組中存儲的順序讀取文件內容,相當多的文件讀取操作是並行進行的,讀取速度根據文件大小決定;ForEach可以保證順序讀取;
其實這種寫法並不常見,因為降低了程序的可讀性,所以不推薦。大多數情況下,我們可以使用數組,好嗎?forEach?解決這個問題的方法:
//callbackforeach.js
var?fs = require(' fs ');
var?files = ['a.txt ',' b.txt ',' c . txt '];
files.forEach(函數?(文件名){
fs.readFile(文件名,' utf-8 ',?功能?(錯誤,內容){
console.log(文件名+ ': ' +內容);
});
});