標籤:return tom 隱式 sep str 全域對象 tracking his 一個
本系列作為Effective JavaScript的讀書筆記。
CSV資料通常都會被某種分隔字元進行分隔。所以在實現CSV Reader時,須要支援不同的分隔字元。那麼,非常自然的一種實現就是將分隔字元作為建構函式的參數。
function CSVReader(separators) {this.separators = separators || [","];this.regexp =new RegExp(this.separators.map(function(sep) {return "\\" + sep[0];}).join("|"));}
對於CSV Reader而言。它的工作原理是首先將讀入的字串依據分行符號切分成為一個個的行。然後對每行依據分隔字元進行切分成為一個個的單元。
所以,能夠使用map方法進行實現:
CSVReader.prototype.read = function(str) {var lines = str.trim().split(/\n/);return lines.map(function(line) {return line.split(this.regexp); // wrong this!});};var reader = new CSVReader();reader.read("a,b,c\nd,e,f\n"); // [["a,b,c"], ["d,e,f"]], wrong result
但是上述代碼中有一個錯誤:傳入到map函數中的回呼函數的this指向有問題。即當中的this.regexp並不能正確的引用到CSVReader執行個體的regexp屬性。因此,最後得到的結果也就是不對的了。
對於這個範例。在map的回呼函數中this指向的實際上是全域對象window。關於this在各種情境下的指向,在Item 18和Item 25中進行了介紹。
為了克服this的指向問題,map函數提供了第二個參數用來指定在其回呼函數中this的指向:
CSVReader.prototype.read = function(str) {var lines = str.trim().split(/\n/);return lines.map(function(line) {return line.split(this.regexp);}, this); // forward outer this-binding to callback};var reader = new CSVReader();reader.read("a,b,c\nd,e,f\n");// [["a","b","c"], ["d","e","f"]]
可是,並非全部的函數都如map考慮的這麼周全。假設map函數不能接受第二個參數作為this的指向。能夠使用以下的方法:
CSVReader.prototype.read = function(str) {var lines = str.trim().split(/\n/);var self = this; // save a reference to outer this-bindingreturn lines.map(function(line) {return line.split(self.regexp); // use outer this});};var reader = new CSVReader();reader.read("a,b,c\nd,e,f\n");// [["a","b","c"], ["d","e","f"]]
這樣的方法將this的引用儲存到了另外一個變數中,然後利用閉包的特性在map的回呼函數中對它進行訪問。一般會使用變數名self來儲存this的引用。當然使用諸如me。that也是可行的。
在ES5環境中。還能夠藉助於函數的bind方法來綁定this的指向(在Item 25中,對該方法進行了介紹):
CSVReader.prototype.read = function(str) {var lines = str.trim().split(/\n/);return lines.map(function(line) {return line.split(this.regexp);}.bind(this)); // bind to outer this-binding};var reader = new CSVReader();reader.read("a,b,c\nd,e,f\n");// [["a","b","c"], ["d","e","f"]]
總結
- 依據函數的調用方式的不同,this的指向也會不同。
- 使用self,me,that來儲存當前this的引用供其它函數使用。
Effective JavaScript Item 37 認識this的隱式指向