本系列作为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-binding
return 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"]]

总结

  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. 给XC2440开发板烧写程序的N种方式

    转:http://blog.chinaunix.net/uid-22030783-id-3420080.html 给XC2440开发板烧写程序非常灵活,总结起来有这么几种方式:   空片烧写(flas ...

  2. Nand Flash与Nor

    转:http://www.360doc.com/content/11/1215/15/1299815_172458274.shtml Flash经常在一些地方被提到,一直没认真去理解它们的区别,因此, ...

  3. ArcGIS 10.2 三维分析工具箱部分工具不能用

    如在以下面的方式操作时发现弹出错误提示, “ Unable to execute the selected tool”... 问题解决方法为: 点击Extensions...,然后把下图中的选项全部勾 ...

  4. Laravel技⃣术⃣特⃣点⃣

    1.Bundle是Laravel的扩展包组织形式或称呼.Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中.你可以选择下载一个扩展包(bundle)然后 ...

  5. jquery load 方法回显数据

    使用jQuery对象.load()方法 load() 方法的作用是可以通过 AJAX 请求从服务器加载数据,并把返回的数据直接放置到指定的元素中. 该方法使用起来非常简单,大大简化了ajax开发 语法 ...

  6. JBoss入门

    很多内容摘自 https://www.jianshu.com/p/4baaf549436b 1.安装目录 安装完Jboss后得目录结构 目录 功能 appclient/ 包含应用程序客户容器的配置细节 ...

  7. echarts图形报表缓存问题(option数据缓存)

    这几天我在工作中用到了echarts开发报表.每次查询出来的数据都是新的,但是echart展现的图形报表却还是之前的数据.网上找了搜索了很多次也没能解决,后面加了技术群才解决的. 我开始已经确定是报表 ...

  8. Mapreduce 测试自带实例 wordcount

    2.7.3版本的hadoop: jar程序所在目录:$HADOOP_HOME/shar/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar 1.本 ...

  9. android APK反编译及代码混淆

    反编译.查看源代码,需要用到两个工具:dex2jar 和 jdgui dex2jar(google code) jdgui(google code),最新版本请见 官方 操作很简单,步骤如下: 1.将 ...

  10. ESP8266学习笔记6:ESP8266规范wifi连接操作

    一.前言 我整理了从2015年至今关于ESP8266的学习笔记,梳理出来了开发环境.基础功能.进阶学习三大部分.方便自己和他人.可点此查看,欢迎交流. 之前在笔记4<ESP8266的SmartC ...