前言

面试中,ES6 是一大考点,当被问到箭头函数时,我们都会说:箭头函数很好用,而且再也不用操心 this 的指向了。
面试官:箭头函数是挺好用的,那有哪些不适合使用箭头函数的场景呢?

箭头函数在大多数情况下,是很好用的,但是为什么在有些场景,使用箭头函数后会产生问题?是不是箭头函数还不够完善?又有哪些场景会发生问题?该如何解决呢?为了防止血案的产生,重新吧这一块拎出来整理巩固一下。

概念

ES6允许使用箭头(=>)定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿名函数的定义

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略;

  2. 函数体如果只有一条语句,则花括号可以省略,并省略return,函数的返回值为该条语句的执行结果;

  3. 箭头函数 this 指向声明时所在作用域下 this 的值;

  4. 箭头函数不能作为构造函数实例化;

  5. 不能使用 arguments;

特性

  1. 箭头函数的this是静态的始终指向函数声明时所在作用域下的this的值;
  2. 不能作为构造实例化对象;
  3. 不能使用 arguments 变量;

箭头函数的写法

为什么叫箭头函数( Arrow Function )?因为它的写法,看上去就是一个箭头:

const multiply = num => num * num;

它等价于:

const multiply = function (num) {return num * num;
};

此外,还可以传多个参数,以及可变参数。

// 多参数
const multiply = (num1, num2) => num1 * num2;// 可变参数
const sum = (num1, num2, ...rest) => {let result = num1 + num2;for (let i = 0; i < rest.length; i++) {result += rest[i];}return result;
};

当有多条语句时,需要配上 {...}return

另外,如果返回的结果是对象,则需要配上 (),像下面这样:

const func = val => ({ value: val });

从上述的写法来看,相较普通函数而言,箭头函数的确简便了很多,提升了我们代码的易用性。但它并非在任何场景下都适用,接下来,将会介绍几种不适合箭头函数的场景,并会提出可行的解决方案。

不适合的场景

1、对象的方法

看下面这个例子:

const obj = {x: 1,print: () => {console.log(this === window); // => trueconsole.log(this.x); // undefined}
};obj.print();

this.x 打印出来是 undefined。为什么?然后,我在上面加了一行,发现 this 指向了 window。

解析:print 方法用了箭头函数,其内部的 this 指向的还是上下文 window,上下文中并没有定义 x,所以 this.x 输出为 undefined。

解决办法:用 ES6 的短语法,或者传统的函数表达式都可以。所以,print 要这样写:

print () {console.log(this === test); // => trueconsole.log(this.x); // 1
}

2、原型方法

同样的规则也适用于原型方法的定义,使用箭头函数会导致运行时的执行上下文错误。

function Cat (name) {this.name = name;
}Cat.prototype.sayCatName = () => {console.log(this === window); // => truereturn this.name;
};const cat = new Cat('Miao');
cat.sayCatName(); // => undefined

解决办法是:用回传统的函数表达式,像下面这样:

Cat.prototype.sayCatName = function () {console.log(this === cat); // => truereturn this.name;
};

sayCatName 变回传统的函数表达式之后,被调用时的执行上下文就会指向新创建的 cat 实例。

3、事件的回调

看下面这个例子:

const btn = document.getElementById('myButton');
btn.addEventListener('click', () => {console.log(this === window); // => truethis.innerHTML = 'Clicked button';
});

这里会有问题,因为 this 指向了 window。

解析:当为一个 DOM 事件绑定回调函数后,触发回调函数时的 this,需要指向当前发生事件的 DOM 节点,也就是这里的 btn。当回调发生时,浏览器会用 btn 的上下文去调用处理函数。所以最后的 this.innerHTML 等价于 window.innerHTML,问题就在这里。

解决办法:用函数表达式代替箭头函数。像这样:

btn.addEventListener('click', function() {console.log(this === btn); // => truethis.innerHTML = 'Clicked button';
});

另外,在 react 中的事件回调,也经常会遇到类似的问题。

// jsx render
<Button onClick={this.handleClickButton.bind(this)}>...
</Button>// callback
handleClickButton () {...
}

注意:这里 onClick 的回调函数,并非字符串,而是一个实实在在的函数。可以将 onClick 理解为一个中间变量,所以 react 在处理函数时的 this 指向就会丢失。

为了解决这个问题,我们需要为回调函数绑定 this,使得事件处理函数无论如何传递,this 都指向我们实例化的那个对象。

在这里,如果用箭头函数,可以这样改写:

<Button onClick={ event => this.handleClickButton(event) }>...
</Button>

箭头函数并没有自己的 this,所以事件处理函数的调用者并不受影响。

4、构造函数

箭头函数不能通过 new 关键字调用。

const Message = (text) => {this.text = text;
};var helloMessage = new Message('Hello World!');
// Uncaught TypeError: Message is not a constructor

解析:从报错信息可以看出,箭头函数没有 constructor 方法,所以不能用作构造函数。 JavaScript 会通过抛出异常的方式,进行隐式地预防。

解决方法:用函数表达式代替箭头函数。

总结

回顾 MDN 给出的解释:箭头函数表达式的语法比函数表达式更短,并且没有自己的this,arguments,super或 new.target。这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数。

所以说,箭头函数无疑是 ES6 带来的重大改进,在正确的场合使用箭头函数,能让代码变得更加简洁短小。但箭头函数也不是万能的,不能用的时候,千万别硬往上套。比如,在需要动态上下文的场景中,使用箭头函数需要格外地小心,这些场景包括:对象的方法、原型方法、事件的回调、构造函数。并非一定要用箭头函数,才能解决问题。

  1. 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
  2. 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法

10分钟理解ES6箭头函数相关推荐

  1. es6 箭头函数 rest参数 扩展运算符

    Es6 箭头函数 语法: 普通函数: fn=function(){} 箭头函数: fn=()=>{} 特性: this是静态的,this始终指向函数声明时所在作用域下的this的值(使用call ...

  2. es6 箭头函数使用_如何使用ES6箭头功能使JavaScript易于阅读

    es6 箭头函数使用 Arrow functions are the new fundamental building blocks of building modern web applicatio ...

  3. es6箭头函数_【知识点】ES6箭头函数、箭头函数与普通函数的区别

    作者:長安曹公子 文章出处:ES6 - 箭头函数.箭头函数与普通函数的区别 一.基本语法 ES6中允许使用箭头=>来定义箭头函数,具体语法,我们来看一个简单的例子: // 箭头函数 let fu ...

  4. 什么时候不该使用es6箭头函数 1

    从开始接触es6到在项目中使用已经有一段时间了,es6有很多优秀的新特性,其中最有价值的特性之一就是箭头函数,他简洁的语法以及更好理解的this值都非常的吸引我.但是新事物也是有两面性的,箭头函数有他 ...

  5. Javascript/ES6箭头函数

    Javascript/ES6箭头函数 文章目录 Javascript/ES6箭头函数 一.箭头函数是什么? 二.箭头函数与普通函数的区别 三.箭头函数的使用 1.箭头函数是匿名函数,不能作为构造函数, ...

  6. ES6箭头函数中的this指向

    1箭头函数中的this (1)箭头函数中没有this : 这意味着 call() apply() bind() 无法修改箭头函数中的this (2)箭头函数中的this指向 :访问上一个作用域的thi ...

  7. ES6箭头函数以及promise/async/await测试案例

    ES6箭头函数的运用 下面以一段代码解释 function one(){return 1 以上函数用箭头函数写步骤,参考下面代码 {}和里面的东西先删去 one = (里面写参数/无参数的里面为空)= ...

  8. [OHIF-Viewers]医疗数字阅片-医学影像-ES6箭头函数(=)

    [OHIF-Viewers]医疗数字阅片-医学影像-ES6箭头函数(=>) https://www.liaoxuefeng.com/wiki/1022910821149312/103154957 ...

  9. 二元函数对xy同时求导_更新丨10分钟掌握高等数学上册函数极限求解问题(考研、期末复习均可以用)...

    学过高数的都知道,极限在高数的应用频率是非常高的,而且是很多高数知识的基础,求导.变限积分求极限.多重积分求极限等等均会用到 虽然是基础,但是很多人在刚学习的时候就会直接被理论弄懵圈,因此就无法继续再 ...

最新文章

  1. python opencv调节图片亮度与对比度
  2. DockerSwarm 微服务部署
  3. 微信公众号点击菜单即可打开并登录微站的实现方法
  4. NYOJ 709 异形卵
  5. 如何做一名出色的屌丝码农?
  6. php字符串如何比较大小写,PHP字符串函数strcmp(二进制安全比较字符串,区分大小写)...
  7. Qt4_使用QXmlStreamReader读取XML
  8. 如何把你的Linux系统变得更加安全
  9. python 黑客书籍 ——扫描+暴力破解
  10. 挖金子修订版开发进行中
  11. 火山PC模拟鼠标操作
  12. VLAN链路类型和接口类型
  13. zabbix 短信发送失败
  14. 安卓,加密drawable图像资源、从类文件生成drawable
  15. 高并发常见的解决方案
  16. win10蓝牙开关不见了_山灵MW200评测:玩转高清蓝牙全编码,MMCX换线耳机必备升级线...
  17. Home School Books美国家庭学校教育小学初中高中全套美语教材
  18. 毛球修剪器单片机开发方案-衣物专属的美容师
  19. java熔断技术_Hystrix熔断器技术解析-HystrixCircuitBreaker
  20. 編程之美2.9:神奇的菲波那契數列

热门文章

  1. 延缓写入失败计算机硬件,Win7提示Windows延缓写入失败怎么解决?
  2. Java IO流详尽解析
  3. CentOS8 生命周期结束切换源
  4. Android 从app中调起小程序(必成)!!!
  5. 老CRT显示器太暗,给亮起来
  6. centos7的scp命令_Linux系统scp命令使用教程
  7. 使用VBA打印二维码和资产标签
  8. AI中Deepfake的部分研究前沿与文献综述
  9. 互融云珠宝玉石区块链应用:解决珠宝行业乱象!
  10. 驾驶证识别 API数据接口