最近被问到了一个问题:

>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. 在ubuntu linux 中编写一个自己的bash脚本

    在ubuntu linux 中编写一个自己的简单的bash脚本. 实现功能:终端中输入简单的命令(以pm为例(play music)),来实现音乐的播放.注:本人ununut中安装了audacious ...

  2. 源码(08) -- java.util.ListIterator<E>

    java.util.ListIterator<E> 源码分析(JDK1.7) ------------------------------------------------------- ...

  3. 从C#到TypeScript - 变量

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  4. SwingBench---ORACLE压力测试工具

    SwingBench---ORACLE压力测试工具 ◆描述SwingBench是Oracle UK的一个员工在一个被抛弃的项目的基础上开发的.目前稳定版本2.5,基于JDK.该工具是免费的,可以在作者 ...

  5. 浅谈-Lambda

    Lambda简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一. 简介: lambda运算符:所有的lambda表达式都是用新的lambda运算符 &qu ...

  6. GAME(A)性能测试过程模型

  7. 随机生成并排序 C,去同,有序数组合并排序

    #include<iostream> #include<stdlib.h> #include<time.h> using namespace std; int ma ...

  8. [原创.数据可视化系列之十三]idw反距离权重插值算法的javascript代码实现

    图形渲染中,idw反距离权重插值算法是一个应用非常广泛的方法,但是js实现的比较少,目前实现一个: //idw算法 //输入[[x:0,y:0,v:0],[x:0,y:0,v:0],[x:0,y:0, ...

  9. JAVA三大特性之二——继承

    很多人在学习了JAVA以后,都会了解这个概念,而且继承也会在以后的开发中经常用到,但对于JAVA的继承特性,很多人都了解的不够深入,不够完整,当然这其中包括我,所以我就想抽点时间来整理一下JAVA继承 ...

  10. Altium Designer(DXP)小技巧之模块化布局

    原创博客转载需注明地址 在我们用Altium Designer进行电路板的绘制的时候经常会遇到模块化布局的问题 就比如电源模块(电源芯片及其外围芯片)放在一起 传感器模块(传感器芯片及其外围芯片)放在 ...