zoukankan      html  css  js  c++  java
  • Effective JavaScript Item 37 认识this的隐式指向

    本系列作为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(/
    /);
    	return lines.map(function(line) {
    		return line.split(this.regexp); // wrong this!
    	});
    };
    var reader = new CSVReader();
    reader.read("a,b,c
    d,e,f
    "); // [["a,b,c"], ["d,e,f"]], wrong result
    

    但是上述代码中有一个错误:传入到map函数中的回调函数的this指向有问题。即当中的this.regexp并不能正确的引用到CSVReader实例的regexp属性。因此,最后得到的结果也就是不对的了。

     

    对于这个样例。在map的回调函数中this指向的实际上是全局对象window。关于this在各种场景下的指向,在Item 18Item 25中进行了介绍。

     

    为了克服this的指向问题,map函数提供了第二个參数用来指定在其回调函数中this的指向:


    CSVReader.prototype.read = function(str) {
    	var lines = str.trim().split(/
    /);
    	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
    d,e,f
    ");
    // [["a","b","c"], ["d","e","f"]]
    

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


    CSVReader.prototype.read = function(str) {
    	var lines = str.trim().split(/
    /);
    	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
    d,e,f
    ");
    // [["a","b","c"], ["d","e","f"]]
    

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

     

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


    CSVReader.prototype.read = function(str) {
    	var lines = str.trim().split(/
    /);
    	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
    d,e,f
    ");
    // [["a","b","c"], ["d","e","f"]]
    

    总结

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


  • 相关阅读:
    MySQL中的排序
    为什么删除记录表文件不会减小?(记录的插入与删除在磁盘上的变化)
    Mysql 中的MDL
    Redis 基础知识点总结
    分布式系统中的CAP理论与Base理论
    Java基础篇(JVM)——Class对象
    Java基础篇(JVM)——类加载机制
    Java基础篇(JVM)——总领
    数据结构与算法小结——排序(八)
    数据结构与算法小结——排序(七)
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7284448.html
Copyright © 2011-2022 走看看