最近被问到了一个问题:

>javaScript 中的箭头函数 (=>) 和普通函数 (function) 有什么区别?

我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答……

>箭头函数中的this和调用时的上下文无关,而是取决于定义时的上下文

这并不是很正确的答案……虽然也不是完全错误

##箭头函数中的 this

首先说我的回答中没有错误的部分:箭头函数中的 this 确实和调用时的上下文无关

```javascript
function make () {
return ()=>{
console.log(this);
}
}

const testFunc = make.call({ name:'foo' });

testFunc(); //=> { name:'foo' }
testFunc.call({ name:'bar' }); //=> { name:'foo' }

```
这个例子可以看到,确实箭头函数在定义之后,this 就不会发生改变了,无论用什么样的方式调用它,this 都不会改变;
但严格来说,这并不是“取决于定义时的上下文”, 因为箭头函数根本就没有声明自己的 this,在箭头函数中调用 this 时,仅仅是**简单的沿着作用域链向上寻找**,找到最近的一个 this 拿来使用罢了;
从效果上看,这和我之前的理解并没有多大偏差,但它们的本质却是截然不同,箭头函数并不是普通函数新增了 this 不受调用时上下文影响的特性,而是减少了很多特性;

##箭头函数其实是更简单的函数

实际上箭头函数中并不只是 this 和普通函数有所不同,箭头函数中没有任何像 this 这样自动绑定的局部变量,包括:this,arguments,super(ES6),new.target(ES6)……
借用别人的一个例子:

```javascript
function foo() {
setTimeout( () => {
console.log("args:", arguments);
},100);
}

foo( 2, 4, 6, 8 );
// args: [2, 4, 6, 8]
```

在普通函数中,会自动绑定上的各种局部变量,箭头函数都是十分单纯的沿着作用域链向上寻找……
箭头函数就是这么个简单、纯粹的东西;
所以我个人认为箭头函数更适合函数式编程,除了它更短以外,使用箭头函数也更难被那些没有显示声明的变量影响,导致你产生意料之外的计算结果;

##那么普通函数能否实现和箭头函数一样的效果呢?

如果是像当初的我一样简单的考虑固定住 this 这个易变的家伙……那倒是很简单,有些常用的方法,比如这样:

```javaScript
function make () {
var self = this;
return function () {
console.log(self);
}
}
```

或者

```javaScript
function make () {
return function () {
console.log(this);
}.bind(this);
}
```
然而第二种方法只能固定 this 这一个变量而已,如前文所述,箭头函数中的 arguments 等变量也是从作用域链中寻找的,为了实现类似的效果,我们只有重新定义一个局部变量这一种方式,而 babel 也是使用这种方式对箭头函数进行处理的。

```javaScript
function make () {
return function () {
console.log(this);
console.log(arguments);
}
}

//babel it...

function make() {
var _this = this,
_arguments = arguments;

return function () {
console.log(_this);
console.log(_arguments);
};
}
```

##那么……如果我想在箭头函数中使用 arguments 该怎么办?

……我觉得如果你有这个需求,可能还是用普通函数更合适一点……
但并不是说在箭头函数中无法以类似数组的形式取到所有参数,我们可以利用展开运算符来接收参数,比如这样:

```javascript
const testFunc = (...args)=>{
console.log(args) //数组形式输出参数
}
```

或许真的有场景需要用到这种写法,但我还是认为,箭头函数更适合那些接受固定的参数,返回一个计算结果的简单情况;

特别感谢 [vajoy](http://www.cnblogs.com/vajoy/) 所译 [getify](https://github.com/getify) 大神的[文章](http://www.cnblogs.com/vajoy/p/4902935.html),把我从错误的理解上引导回来;
同时也让我明白了,有些时候**代码运行的结果和你的预期相同,未必就代表代码运行的原理和你的理解相同**

JS中的普通函数和箭头函数的更多相关文章

  1. js中escape对应的C#解码函数 UrlDecode

    js中escape对应的C#解码函数 System.Web.HttpUtility.UrlDecode(s),使用过程中有以下几点需要注意   js中escape对应的C#解码函数 System.We ...

  2. JavaScript中的普通函数和箭头函数

    最近被问到了一个问题: javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答 ...

  3. 前端项目中常用es6知识总结 -- 箭头函数及this指向、尾调用优化

    项目开发中一些常用的es6知识,主要是为以后分享小程序开发.node+koa项目开发以及vueSSR(vue服务端渲染)做个前置铺垫. 项目开发常用es6介绍 1.块级作用域 let const 2. ...

  4. 普通函数跟箭头函数中this的指向问题

    箭头函数和普通函数的区别如下. 普通函数:根据调用我的人(谁调用我,我的this就指向谁) 箭头函数:根据所在的环境(我再哪个环境中,this就指向谁) 一针见血式总结: 普通函数中的this: 1. ...

  5. js中bind、call、apply函数的用法

    最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但 ...

  6. js中bind、call、apply函数的用法 (转载)

    最近看了一篇不错的有关js的文章,转载过来收藏先!!! 最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web 的项目,然后在腾讯实习的时候用 j ...

  7. js中各个排序算法和sort函数的比较

    js中要实现数据排序,其实只需要用sort函数就能很好的满足了,但是我今天想知道他和其他排序算法的区别,比如耗时呀等.测了一组数据如下: // ---------- 一些排序算法 Sort = {} ...

  8. 箭头函数中可改变this作用域,回调函数用箭头函数this指向page,自定义事件用箭头函数this指向undefined

    1.回调函数中,用箭头函数改变this的作用域 success: (res)=>{ this.setData({ //此时,this指向page页面 ... }) } 2.自定义事件中,如果使用 ...

  9. js函数( 普通函数、箭头函数 ) 内部this的指向

    - 普通函数   | 具名普通函数.匿名普通函数,在不作为对象的属性值的情况下,其内部的 this 总是指向代码运行环境下的全局对象 ( 例如,浏览器中的 window ). 示例: (functio ...

随机推荐

  1. java的位运算符

    1.与运算&,同为1为1,否则为0: 例如:10001(二进制)&10000(二进制)=10000(二进制) 2.或运算|,只要有1就是1: 例如:10001(二进制)&100 ...

  2. Linux编程之ICMP洪水攻击

    我的上一篇文章<Linux编程之PING的实现>里使用ICMP协议实现了PING的程序,ICMP除了实现这么一个PING程序,还有哪些不为人知或者好玩的用途?这里我将介绍ICMP另一个很有 ...

  3. c语言中,有符号数位移

    #include <stdio.h> int main(void) { unsigned i = 0xcffffff3; long j=0xcffffff3; int k=0xcfffff ...

  4. Sublime Text 3 修改插件安装位置【sublime text、插件路径、Data】

    直接切入正题,在享受Sublime 插件给我们带来开发效率的同时,有些插件的文件也是很大的,但是插件默认安装的位置是AppData的目录[C:\Users\用户名\AppData\Roaming\Su ...

  5. php正则表达式(持续更新)

    1.字符串替换多个关键字 $pattern = array('/a/', '/a/', '/a/'); $replacement = array('x', 'y', 'z'); $subject = ...

  6. 表单界面的兼容PC手机端解决方案

    就当写一篇随笔吧~上星期还在做加盟模块(兼容微信端),这星期已经加班做快递扫码模块(react+node),所以我感觉只有弹药备足了才能稍微轻松些应对各种需求.实话说在同个部门的大佬面前差距确实大,如 ...

  7. python 库安装笔记

    python 库安装笔记 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-2-22 友情提示 安装python库的过程中 ...

  8. 解决CSS中float:left后需要clear:both清空

    现在,大部分的横排导航都是通过 ul -> li *n -> a 来实现的.具我所知,要达到这种效果,有几种方法可以实现. 1.传统处理方式: li {float:left;}/*这样,对 ...

  9. c++ 调用dl里的导出类

    来源:http://blog.csdn.net/yysdsyl/article/details/2626033 动态dll的类导出:CPPDll2->test.h #pragma once // ...

  10. loadrunner11.0之IP欺骗

    一:设置虚拟ip地址 操作步骤: 1:添加ip地址 运行loadrunner---tools---IP wizard 2:选择create  new setting,点击"下一步" ...