> ## Content Index
> Fetch the complete content index at: https://blog.hacking.pub/llms.txt
> Use this file to discover other available public pages before exploring further.

# js 匿名函数 箭头函数
- URL: https://blog.hacking.pub/2017/07/18/js-ni-ming-han-shu-jian-tou-han-shu/
- Published: 2017-07-18T19:03:15.000Z
- Updated: 2017-07-18T19:05:14.000Z
- Author: chainhelen
- Tags: js, nodejs, 匿名函数, 箭头函数

#### 关于new

首先回顾一下new关键字

```
var ch = new Fa();
等价于
var ch = {};
ch.__prototype__ = Fa.prototype;
Fa.call(ch);

```

本质上call的第一个参数可以理解传入了一个this，改变了整个上下文

#### 本文事例

运行环境 nodejs v7.7.2

拿一段观察者模式的代码来看

```
//js文件
function Event() {
    this.handlers = {};
}

Event.prototype.on = function(type, cb) {
    //exception handler, need to code
    if("undefined" == typeof this.handlers[type]) {
        this.handlers[type] = [];
    }

    this.handlers[type].push(cb);
}

Event.prototype.emit = function(type) {
    //exception handler, need to code
    if(this.handlers[type]) {
        let funs = this.handlers[type];
        for(let idx in funs) {
            let fun = funs[idx];
            setTimeout(fun, 0);
        }
    }
}

let eve = new Event();
eve.on("add", () => {
    console.log("add");
});
eve.on("del", () => {
    console.log("del");
});
eve.emit("del");
eve.emit("add");

```

如果上述的prototype属性赋值，将匿名函数修改成箭头函数，那么就会出问题  
![js 匿名函数 箭头函数.png](https://blog.hacking.pub/qiniu/js%20%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%20%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0/js%20%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%20%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0.png)

这是因为箭头函数中`this`是指向词法作用域，这里面是全局变量module的属性`exports`，而不是对象`eve`

可以使用一下代码验证

```
function Event() {
    this.handlers = {};
}

Event.prototype.on = (type, cb) => {

//++
    console.log(this.wwww);

    //exception handler, need to code
    if("undefined" == typeof this.handlers[type]) {
        this.handlers[type] = [];
    }

    this.handlers[type].push(cb);
}

Event.prototype.emit = (type) => {
    //exception handler, need to code
    if(this.handlers[type]) {
        let funs = this.handlers[type];
        for(let idx in funs) {
            let fun = funs[idx];
            setTimeout(fun, 0);
        }
    }
}

//++
this.wwww =  "wwww";
console.log(this === exports);

let eve = new Event();
eve.on("add", () => {
    console.log("add");
});
eve.on("del", () => {
    console.log("del");
});
eve.emit("del");
eve.emit("add");

```

#### 延伸

如下js代码

```
this.wwww = "wwww";
var a = function() {
    console.log(this.wwww);
}
a();

function b() {
    console.log(this.wwww);
}
b();

var c = () => console.log(this.wwww);
c();

```

使用nodejs命令执行如上代码的js文件，输出的是

```
undefined
undefined
wwww

```

但是在终端里(或者chrome浏览器中)，输出的是

```
wwww
wwww
wwww

```

这是因为在终端里，this就是指向全局变量`global`，故而在对象`Global`上会添加上`www`，`a`, `b`, `c`等等属性，运行时会取到调用者`global`wwww属性

在js文件，this指向的是`exports`对象(属性)，同时`a`,`b`，`c`属性并列  
如下图所示

![js 匿名函数 箭头函数.png](https://blog.hacking.pub/qiniu/js%20%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%20%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0/js%20%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%20%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B02.png)

也就是说`c`使用了箭头函数，内部`this`指向了`词法作用域`(措辞可能不准确，这里指变量`exports`)，那么就可以找到属性`wwww`

可以使用如下js文件验证

```
function b() {
    console.log(this === global);
    console.log(this.wwww);
}
b();

```

#### 参考

[彻底理解js中this的指向，不必硬背](http://www.cnblogs.com/pssp/p/5216085.html?ref=blog.hacking.pub)