新事物也是有两面性的,箭头函数有他的便捷有他的优点,但是他也有缺点,他的优点是代码简洁,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. bzoj 4131: 并行博弈 (parallel)

    bzoj 4131: 并行博弈 (parallel) Description lyp和ld在一个n*m的棋盘上玩翻转棋,游戏棋盘坐标假设为(x, y),1 ≤ x ≤ n,1 ≤ y ≤ m,这个游戏 ...

  2. include和require的区别误区

    面试时总会被问到include和require的区别,回答的时候一般也是有以下几种区别: 1.include引入文件的时候,如果碰到错误,会给出警告,并继续运行下边的代码. require引入文件的时 ...

  3. bzoj 2503 相框 分类讨论

    题目大意:给定一张无向图,每次可以进行以下两种操作: 1.将一个点分裂成一些点,原先这个点连接的每条边任选一个新点进行连接 2.将两个度数为1的点合并为1个点 求将这个图变成一个环的最小操作次数 我们 ...

  4. git refs 详解

    https://blog.csdn.net/taiyangdao/article/details/52766424 http://www.chenchunyong.com/2017/01/06/git ...

  5. 转:mysql 索引

    转:mysql 索引 文章归属:http://feiyan.info/16.html,我想自己去写了,但是发现此君总结的非常详细.直接搬过来了 关于MySQL索引的好处,如果正确合理设计并且使用索引的 ...

  6. 【Visual Studio】Visual Studio 2010 "LNK1123: 转换到 COFF 期间失败: 文件无效或损坏" 的解决方法

    1.将 项目|项目属性|配置属性|连接器|清单文件|嵌入清单 “是”改为“否”. 2.找到 C:\Windows\winsxs\x86_netfx-cvtres_for_vc_and_vb_b03f5 ...

  7. Python 函数的一般形式及参数

    #!/usr/bin/env python # -*- coding:utf-8 -*- # @Time : 2017/11/01 21:46 # @Author : lijunjiang # @Fi ...

  8. 安装python 2.7

    安装包下载地址 windows:https://www.python.org/ftp/python/2.7.14/python-2.7.14.amd64.msi linux: https://www. ...

  9. Linux文件的权限与属性

    由于以前学习Linux的时候没有做比较全面的总结笔记,而且平时大部分工作都在windows上进行,所以关于Linux的一些知识点有所遗忘.近期难得空闲,翻阅书籍,学习<鸟哥的Linux私房菜&g ...

  10. AC日记——集合位置 洛谷 P1491

    集合位置 思路: 次短路: 先走一遍最短路: 记录最短路径,然后依次删边走最短路: 最短的长度就是次短路: 来,上代码: #include <queue> #include <cma ...