新事物也是有两面性的,箭头函数有他的便捷有他的优点,但是他也有缺点,他的优点是代码简洁,this提前定义,但他的缺点也是这些,比如代码太过简洁,导致不好阅读,this提前定义,导致无法使用JS进行一些ES5里面看起来非常正常的操作。

本质来说箭头函数没有自己的this,它的this是派生而来的,根据“词法作用域”派生而来。

由于箭头函数在调用时不会生成自身作用域下的thisarguments值,其持有外部包含它的函数的this值,并且在调用的时候就定下来了,不可动态改变,下面我就总结一下什么情况下不该使用箭头函数。

在对象上定义函数

const test = {
array: [1, 2, 3],
sum: () => {
console.log(this === window); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
// TypeError: Cannot read property 'reduce' of undefined

原因就是,箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域。

对象方法内的this指向调用这个方法的对象,如果使用箭头函数,this和对象方法在调用的时候所处环境的this值一致。因为 test.sum()是在全局环境下进行调用,此时this指向全局。

解决方法也很简单,使用函数表达式或者方法简写(ES6 中已经支持)来定义方法,这样能确保 this 是在运行时是由包含它的上下文决定的。

const test = {
array: [1, 2, 3],
sum() {
console.log(this === test); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
// 6

定义原型方法

在对象原型上定义函数也是遵循着一样的规则

function Person(name) {
this.name = name;
} Person.prototype.sayName = () => {
console.log(this === window); // => true
return this.name;
}; const cat = new Person('Mew');
cat.sayName(); // => undefined

使用传统的函数表达式就能解决问题

function Person(name) {
this.name = name;
} Person.prototype.sayName = function() {
console.log(this === Person); // => true
return this.name;
}; const cat = new Person('Mew');
cat.sayName(); // => Mew

定义事件回调函数

thisJS中非常强大的特点,他让函数可以根据其调用方式动态的改变上下文,然后箭头函数直接在声明时就绑定了this对象,所以不再是动态的。

在客户端,在DOM元素上绑定事件监听函数是非常普遍的行为,在DOM事件被触发时,回调函数中的this指向该DOM,但是,箭头函数在声明的时候就绑定了执行上下文,要动态改变上下文是不可能的,在需要动态上下文的时候它的弊端就凸显出来:

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

因为这个回调的箭头函数是在全局上下文中被定义的,所以他的thiswindow。换句话说就是,箭头函数预定义的上下文是不能被修改的,这样 this.innerHTML 就等价于 window.innerHTML,而后者是没有任何意义的。

使用函数表达式就可以在运行时动态的改变 this

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

定义构造函数

如果使用箭头函数会报错。

显然,箭头函数是不能用来做构造函数。

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

理论上来说也是不能这么做的,因为箭头函数在创建时this对象就绑定了,更不会指向对象实例。

太简短的(难以理解)函数

箭头函数可以让语句写的非常的简洁,但是一个真实的项目,一般由多个开发者共同协作完成,箭头函数有时候并不会让人很好的理解:

const multiply = (a, b) => b === undefined ? b => a * b : a * b;
const double = multiply(2);
double(3); // => 6
multiply(2, 3); // => 6

代码看起来很简短,但大多数人第一眼看上去可能无法立即搞清楚它干了什么。

这个函数的作用就是当只有一个参数a时,返回接受一个参数b返回a*b的函数,接收两个参数时直接返回乘积。

为了让这个函数更好的让人理解,我们可以为这个箭头函数加一对花括号,并加上return语句,或者直接使用函数表达式:

function multiply(a, b) {
if (b === undefined) {
return function(b) {
return a * b;
}
}
return a * b;
} const double = multiply(2);
double(3); // => 6
multiply(2, 3); // => 6

毫无疑问,箭头函数带来了很多便利。恰当的使用箭头函数可以让我们避免使用早期的.bind()函数或者需要固定上下文的地方并且让代码更加简洁。

箭头函数也有一些不便利的地方。我们在需要动态上下文的地方不能使用箭头函数:定义对象方法、定义原型方法、定义构造函数、定义事件回调函数。在其他情况下,请尽情的使用箭头函数。

ES6使用箭头函数注意点的更多相关文章

  1. ES6中箭头函数的作用

    我们知道在ES6中,引入了箭头函数,其本质就是等同有ES5中的函数.类似于下面的写法: let test1=() => “abc”; let test2=() => { return “a ...

  2. Es6中箭头函数与普通函数的区别

    Es6中箭头函数与普通函数的区别? 普通function的声明在变量提升中是最高的,箭头函数没有函数提升 箭头函数没有属于自己的this,arguments 箭头函数不能作为构造函数,不能被new,没 ...

  3. es6的箭头函数和es5的function函数区别

    一.es6的箭头函数es6箭头函数内部没有this,使用时会上朔寻找最近的this不可以做构造函数,不能使用new命令,因为没有this函数体内没有arguments,可以使用rest参数代替不能用y ...

  4. Es6 之箭头函数 初学

    不积跬步,无以至千里;不积小流,无以成江海! // ES5 var selected = allJobs.filter(function (job) { return job.isSelected() ...

  5. 关于es6的箭头函数使用与内部this指向

    特型介绍:箭头函数是ES6新增的特性之一,它为JS这门语言提供了一种全新的书写函数的语法. 'use strcit'; let arr = [1,2,3]; //ES5 let es5 = arr.m ...

  6. ES6笔记② 箭头函数

    特性介绍 箭头函数是ES6新增的特性之一,它为JS这门语言提供了一种全新的书写函数的语法. //ES5 function fun(x,y){ return x+y; } console.log(fun ...

  7. 关于ES6 用箭头函数后的 this 指向问题

    最近写完小程序后, 开始学习React, 因为有编译器, 就直接用ES6 新语法了, 中间自然离不开  () => { console.log('箭头函数的this是指向哪的问题')}; var ...

  8. 进阶路上有你我-相互相持篇之ES6里箭头函数里的this指向问题

    首先复习下普通函数里的this指向: function test(){ console.log(this) } test() 你会秒杀的毫无疑问的回答:window,针对普通函数:谁调用了函数  函数 ...

  9. es6之箭头函数

    => 箭头函数是ES6增加的函数表达式.将function关键字和函数名都删掉,并使用“=>”连接参数列表和函数体(低版本浏览器不支持) 箭头函数看上去只是语法的变动,其实也影响了this ...

  10. ES6学习--箭头函数

    1. 箭头函数基本形式 let func = (num) => num; let func = () => num; let sum = (num1,num2) => num1 + ...

随机推荐

  1. canvas小图123

    1 绘制扇形图 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  2. CSS 五种方式实现 Footer 置底

    CSS 五种方式实现 Footer 置底   页脚置底(Sticky footer) 就是让网页的footer部分始终在浏览器窗口的底部. 当网页内容足够长以至超出浏览器可视高度时,页脚会随着内容被推 ...

  3. AtCoder Regular Contest 075 C D E (暂时)

    C - Bugged 题意 给\(n\)个数,找其中的一个子集,使得其和最大,且不是\(10\)的整数倍. 思路 先对\(n\)个数求和, 如果本身即不被\(10\)整除,则即为答案. 否则,如果本身 ...

  4. Android下设置CPU核心数和频率

    现在的Android手机双核.四核变得非常普遍,同时CPU频率经常轻松上2G,功耗肯定会显著增加.而大多数的ARM架构的CPU采用的是对称多处理(SMP)的方式处理多CPU.这就意味着每个CPU核心是 ...

  5. Python 文本(txt) 转换成 EXCEL(xls)

    #!/bin/env python # -*- encoding: utf-8 -*- #------------------------------------------------------- ...

  6. window golang1.12.4 安装配置&IDE vscode

    step 1:下载golang golang官网地址是 https://golang.org/dl/ 如果没有墙的话,可以用这个地址 https://golang.google.cn/dl/ 如图: ...

  7. 链表ADT的实现

    list.h文件 /*链表的类型声明*/ typedef int ElementType; /* START: fig3_6.txt */ #ifndef _List_H #define _List_ ...

  8. AC日记——琪露诺 洛谷 P1725

    琪露诺 思路: 单调队列+dp: 然而劳资不会单调队列,所以,线段树水过; 来,上代码: #include <cstdio> #include <cstring> #inclu ...

  9. Codeforces 916E Jamie and Tree (换根讨论)

    题目链接  Jamie and Tree 题意  给定一棵树,现在有下列操作: $1$.把当前的根换成$v$:$2$.找到最小的同时包含$u$和$v$的子树,然后把这棵子树里面的所有点的值加$x$: ...

  10. Codeforces 761D Dasha and Very Difficult Problem(贪心)

    题目链接 Dasha and Very Difficult Problem 求出ci的取值范围,按ci排名从小到大贪心即可. 需要注意的是,当当前的ci不满足在这个取值范围内的时候,判为无解. #in ...