浅谈ES6中箭头函数与普通函数的区别
作者:ほうこう
一、箭头函数的基本语法示例
ES6中允许使用箭头 => 来定义箭头函数,具体语法,我们来看一个简单的例子:
// 箭头函数 let fun1 = (name) => { return `Hello ${name} !`; }; fun1('我是箭头函数'); //Hello 我是箭头函数 !" // 箭头函数只有一个参数,可以省去参数括号() let fun2 = name => { return `Hello ${name} !`; }; fun2('我是箭头函数'); //Hello 我是箭头函数 !" // 箭头函数如果函数体只有一句代码,可以省去函数体的大括号{ } let fun3 = name => `Hello ${name} !`; fun3('我是箭头函数'); //Hello 我是箭头函数 !" // 普通函数 let fun4 = function (name) { return `Hello ${name} !`; // 函数体 }; fun4('我是普通函数'); //Hello 我是普通函数 !"
从上面的基本语法示例中可以看出,箭头函数的定义要比普通函数定义简洁、清晰得多,很快捷。
二、箭头函数和普通函数得区别
1、箭头函数的this指向问题(重要)
箭头函数没有自己的
this
,它会获取自己在定义时(注,是定义时,不是调用时)所处的外层执行环境的this
,并继承这个this
值。所以,箭头函数中this
的指向在它被定义的时候就已经确定了,之后永远不会改变。
var name = 'Global'; function fun1() { //返回一个普通函数 return function () { console.log(this.name); } } function fun2() { //返回一个箭头函数 return () => { console.log(this.name); } } fun1().call({name: 'Obj'}); // 'Obj' fun2().call({name: 'Obj'}); // 'Global'
从上面实例看出
fun1
返回的是一个普通函数,此时,通过 call
改变普通函数的 this
成功的将普通函数的 this
指向了 {name: 'Obj'}
所以输出 Obj
fun2
返回的是一个箭头函数,由于箭头函数的 this
是在初始化的时候就被定义了,然而它继承了它外层 fun2
的执行环境中的 this
,fun2
里面的this
又继承了全局的this
,所以输出 Global
再看一个实例
var name = 'Global'; var obj = { name: 'Obj', fun1: function(){ console.log(this.name); }, fun2: () => { console.log(this.name); } }; obj.fun1(); // 'Obj' obj.fun2(); // 'Global'
从这个实例可以看出
对象obj
里面的fun1
是一个普通函数,普通函数作为对象的方法调用时, this
指向它所属的对象。此时 this
指向的是当前对象,所以返回 Obj
对象obj
里面的fun2
是一个箭头函数,箭头函数的this
是在定义初始化的时候继承它所处的执行环境当中的this
,当前fun2所处的执行环境是 Window
,所以返回 Global
2、call() apply() bind()无法改变箭头函数中this的指向
由于
this
已经在箭头函数定义时候就被绑定,通过call() apply() bind()
调用时,只是传入了参数而已,对this
并没有什么影响
var name = 'Global'; // 箭头函数定义在全局作用域 let fun = () => { console.log(this.name) }; fun(); // 'Global' // this的指向不会改变,永远指向Window对象 fun.call({name: 'Obj'}); // 'Global' fun.apply({name: 'Obj'}); // 'Global' fun.bind({name: 'Obj'})(); // 'Global'
因此箭头函数不能被修改this
指向
3、间接修改箭头函数的this指向
如果我们在某个场景里面非要修改箭头函数的 this
指向呢
var name = 'Global'; function fun() { //返回一个箭头函数 return () => { console.log(this.name); } } fun()() // 'Global' fun.call({ name: 'Obj' })() // Obj
上面实例中看出fun
是一个普通函数,返回一个箭头函数,我们通过call修改fun 这个普通函数的 this
, 此时箭头函数刚好继承的是这个普通函数的 this
, 所以返回 Obj
, 从而达到间接修改箭头函数的this
指向问题
3、箭头函数不能被new运算符
通过new去实例化一个箭头函数的时候,会报错
var Foo = () => {}; var foo = new Foo(); //Foo is not a constructor
原因:构造函数的new都做了些什么?简单来说,分为四步
js
内部首先会先生成一个对象;- 再把函数中的
this
指向该对象; - 然后执行构造函数中的语句;
- 最终返回该对象实例。
由于箭头函数没有自己的this
,它的this
是继承外部执行环境中的this
,这个时候通过new
运算符进行实例化时候,且this
指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用
4、箭头函数没有原型prototype
let Foo = () => { console.log('Hello World !') }; console.log(Foo.prototype); // undefined
5、箭头函数没有arguments,然而可用 REST参数,扩展运算符(三个点)...解决
// 普通函数 function fun1() { console.log(arguments) } //箭头函数 let fun2 = () => { console.log(arguments) }; fun1(1,2); // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ] fun2(1,2); // arguments is not defined
可以看出箭头函数是没有arguments
得,不过不用担心,箭头函数得替代方法是用扩展运算符(三个点)...解决
let fun = (...args) => { console.log(args) }; fun(1,2); // [1, 2]
6、箭头函数不能换行
let fun = () => 1; // SyntaxError: expected expression, got '=>'
7、箭头函数一条语句返回对象字面量,需要加括号
let fun = () => { foo: 1 }; fun(); // undefined let fun1 = () => ({ foo: 1 }); fun1(); // {foo: 1} let fun2 = () => { foo: function() {} }; // SyntaxError: function statement requires a name let fun3 = () => ({ foo: function() {} });
8、箭头函数的解析顺序相对||靠前
let fun = false || function() {}; // ok let fun1 = false || () => {}; // Malformed arrow function parameter list let fun2 = false || (() => {}); // ok
9、箭头函数不能用作Generator函数,不能使用yeild关键字
yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器。。
三、参考资料
四、结束语
到此这篇关于浅谈ES6中箭头函数与普通函数的区别的文章就介绍到这了,更多相关ES6 箭头函数与普通函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!