浅谈ES6中箭头函数与普通函数的区别

 更新时间:2023年05月23日 11:25:06   作者:ほうこう  
箭头函数是ES6中一种新的函数的表达式,本文就来介绍一下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 的执行环境中的 thisfun2 里面的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 箭头函数与普通函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 出现“不能执行已释放的Script代码”错误的原因及解决办法

    出现“不能执行已释放的Script代码”错误的原因及解决办法

    出现“不能执行已释放的Script代码”错误的原因及解决办法...
    2007-08-08
  • BootStrap table使用方法分析

    BootStrap table使用方法分析

    这篇文章主要为大家详细介绍了JS组件Bootstrap Table使用方法,具有一定的实用性和参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • javascript md5加密代码

    javascript md5加密代码

    javascript md5加密代码,和asp、php的加密有一定的区别
    2008-09-09
  • 移动web开发之touch事件实例详解

    移动web开发之touch事件实例详解

    下面小编就为大家分享一篇移动web开发之touch事件实例详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • 使用javascript为网页增加夜间模式

    使用javascript为网页增加夜间模式

    如何给Web页面增加夜间模式功能? 其实所谓的夜间模式就是在页面上增加一个透明的遮罩层,但是遮罩层会挡住页面元素, 解决方法是 添加DIV,给DIV的outline属性一个很大的outline-width值,用outline的边框作为遮罩,这样既能正常点击页面元素,又能达到夜间模式的效果
    2014-01-01
  • JS扩展String.prototype.format字符串拼接的功能

    JS扩展String.prototype.format字符串拼接的功能

    这篇文章主要介绍了JS扩展String.prototype.format字符串拼接的功能,需要的朋友可以参考下
    2018-03-03
  • 如何基于小程序实现发送语音消息及转文字功能

    如何基于小程序实现发送语音消息及转文字功能

    最近为小程序增加语音识别转文字的功能,坑路不断,特此记录,下面这篇文章主要给大家介绍了关于如何基于小程序实现发送语音消息及转文字功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • 使用JavaScript字符串解决回文数的方案详解

    使用JavaScript字符串解决回文数的方案详解

    这篇文章主要介绍了使用JavaScript字符串解决回文数的方案,JavaScript中的字符串是一种数据类型,用于表示文本数据,字符串可以包含任意字符序列,包括字母、数字、符号和空格,灵活掌握字符串的解决问题思想,巧用字符串解决回文数,需要的朋友可以参考下
    2024-05-05
  • js实现模态窗口增加与删除

    js实现模态窗口增加与删除

    这篇文章主要为大家详细介绍了js实现模态窗口增加与删除,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • 5个经过实战验证的JavaScript性能优化技巧分享

    5个经过实战验证的JavaScript性能优化技巧分享

    在现代Web开发中,JavaScript性能优化是每个开发者都必须面对的挑战,本文将揭示5个经过实战验证的JavaScript性能优化技巧,其中第三个技巧更是被90%的开发者所忽视,需要的朋友可以参考下
    2026-03-03

最新评论