本系列作为Effective JavaScript的读书笔记。

CSV数据通常都会被某种分隔符进行分隔。所以在实现CSV Reader时,须要支持不同的分隔符。那么,非常自然的一种实现就是将分隔符作为构造函数的參数。

  1. function CSVReader(separators) {
  2. this.separators = separators || [","];
  3. this.regexp =
  4. new RegExp(this.separators.map(function(sep) {
  5. return "\\" + sep[0];
  6. }).join("|"));
  7. }

对于CSV Reader而言。它的工作原理是首先将读入的字符串依据换行符切分成为一个个的行。然后对每行依据分隔符进行切分成为一个个的单元。

所以,能够使用map方法进行实现:

  1. CSVReader.prototype.read = function(str) {
  2. var lines = str.trim().split(/\n/);
  3. return lines.map(function(line) {
  4. return line.split(this.regexp); // wrong this!
  5. });
  6. };
  7. var reader = new CSVReader();
  8. 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的指向:

  1. CSVReader.prototype.read = function(str) {
  2. var lines = str.trim().split(/\n/);
  3. return lines.map(function(line) {
  4. return line.split(this.regexp);
  5. }, this); // forward outer this-binding to callback
  6. };
  7. var reader = new CSVReader();
  8. reader.read("a,b,c\nd,e,f\n");
  9. // [["a","b","c"], ["d","e","f"]]

可是,并非全部的函数都如map考虑的这么周全。假设map函数不能接受第二个參数作为this的指向。能够使用以下的方法:

  1. CSVReader.prototype.read = function(str) {
  2. var lines = str.trim().split(/\n/);
  3. var self = this; // save a reference to outer this-binding
  4. return lines.map(function(line) {
  5. return line.split(self.regexp); // use outer this
  6. });
  7. };
  8. var reader = new CSVReader();
  9. reader.read("a,b,c\nd,e,f\n");
  10. // [["a","b","c"], ["d","e","f"]]

这样的方法将this的引用保存到了另外一个变量中,然后利用闭包的特性在map的回调函数中对它进行訪问。一般会使用变量名self来保存this的引用。当然使用诸如me。that也是可行的。

在ES5环境中。还能够借助于函数的bind方法来绑定this的指向(在Item
25中,对该方法进行了介绍):

  1. CSVReader.prototype.read = function(str) {
  2. var lines = str.trim().split(/\n/);
  3. return lines.map(function(line) {
  4. return line.split(this.regexp);
  5. }.bind(this)); // bind to outer this-binding
  6. };
  7. var reader = new CSVReader();
  8. reader.read("a,b,c\nd,e,f\n");
  9. // [["a","b","c"], ["d","e","f"]]

总结

  1. 依据函数的调用方式的不同,this的指向也会不同。
  2. 使用self,me,that来保存当前this的引用供其它函数使用。

Effective JavaScript Item 37 认识this的隐式指向的更多相关文章

  1. Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数

    本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...

  2. Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表

    本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...

  3. Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合

    本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...

  4. Effective JavaScript Item 10 避免使用with

    本系列作为Effective JavaScript的读书笔记. Item 9:避免使用withkeyword 重点: 设计withkeyword本来是为了让代码变简洁,可是却起到了相反的效果.比方: ...

  5. Effective JavaScript Item 39 绝不要重用父类型中的属性名

    本系列作为Effective JavaScript的读书笔记. 假设须要向Item 38中的Actor对象加入一个ID信息: function Actor(scene, x, y) { this.sc ...

  6. Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__

    本系列作为Effective JavaScript的读书笔记. 在ES5中引入了Object.getPrototypeOf作为获取对象原型对象的标准API.可是在非常多运行环境中.也提供了一个特殊的_ ...

  7. Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数

    作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...

  8. Effective JavaScript Item 30 理解prototype, getPrototypeOf和__proto__的不同

    本系列作为Effective JavaScript的读书笔记. prototype,getPropertyOf和__proto__是三个用来訪问prototype的方法.它们的命名方式非常类似因此非常 ...

  9. Effective JavaScript Item 49 对于数组遍历,优先使用for循环,而不是for..in循环

    本系列作为Effective JavaScript的读书笔记. 对于以下这段代码,能看出最后的平均数是多少吗? var scores = [98, 74, 85, 77, 93, 100, 89]; ...

随机推荐

  1. IIS服务器80端口却已被占用的问题

    一.问题背景 在IIS中发布一个asp网站,发现无法使用80端口,错误为“无法启动该网站.其它网站可能正在使用同一端口”.但其实IIS的其它网站已经没有使用该端口了.这就需要设计到,找到那个进程占用这 ...

  2. JS的join方法

    join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 例子 1 在本例中,我们将创建一个数组,然后把它的所有元素放入一个字符串: <script type ...

  3. 《Go语言实战》笔记之第三章 ----包

    原文地址: http://www.niu12.com/article/10 ####包 所有的.go 文件,除了空行和注释,都应该在第一行声明自己所属的包. 每个包都在一个单独的目录里. 不能把多个包 ...

  4. AWR Report 关键参数详细分析

    WORKLOAD REPOSITORY report for DB Name DB Id Instance Inst num Startup Time Release RAC CALLDB 12510 ...

  5. sql server阻塞(block)处理

    sp_who2 ACTIVE --从下图可知spid = 65进程被76阻塞 --或 * FROM sys.sysprocesses WHERE blocked <> 0 ) --查看阻塞 ...

  6. javascript 中contentWindow和 frames和iframe之间通信

    iframe父子兄弟之间通过jquery传值(contentWindow && parent),iframe的调用包括以下几个方面:(调用包含html dom,js全局变量,js方法) ...

  7. 两张表的笛卡尔积用sql语句

    第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小SELECT * FROM table1 CROSS JOIN table2

  8. 什么是JSONP?

    一.先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助 ...

  9. [Python爬虫] 之十:Selenium +phantomjs抓取活动行中会议活动

    一.介绍 本例子用Selenium +phantomjs爬取活动树(http://www.huodongshu.com/html/find_search.html?search_keyword=数字) ...

  10. Python 操作 ElasticSearch

    Python 操作 ElasticSearch 学习了:https://www.cnblogs.com/shaosks/p/7592229.html 官网:https://elasticsearch- ...