一篇讲透:箭头函数、普通函数有什么区别

前言

 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步!

 🍅 个人主页:南木元元


目录

什么是箭头函数

箭头函数和普通函数的区别

更简洁的语法

箭头函数没有自己的this

箭头函数的this不会改变

箭头函数没有prototype属性

箭头函数不能作为构造函数

箭头函数不能使用arguments对象

箭头函数不能用作Generator函数

箭头函数不适用的场景

结语 


什么是箭头函数

箭头函数是ES6(ECMAScript 6)新增的使用箭头(=>)语法定义函数表达式的能力。任何可以使用函数表达式的地方,都可以使用箭头函数,并且它的语法比传统的函数表达式更加简洁。

// 函数表达式
let functionExpressionSum = function(a, b) {return a + b;
}// 箭头函数
let arrowSum = (a, b) => {return a + b;
}

下面就来详细讲解一下箭头函数和普通函数的区别。

箭头函数和普通函数的区别

更简洁的语法

  • 如果只有一个参数,可以不用括号。只有没有参数或多个参数的情况下,才需要使用括号。
// 只有一个参数,可以不用括号,以下两种写法都有效
let double = (x) => { return 2 * x; };
let triple = x => { return 3 * x; };// 没有参数需要括号
let getRandom = () => { return Math.random(); };// 多个参数需要括号
let sum = (a, b) => { return a + b; };// 无效的写法:
let multiply = a, b => { return a * b; };
  • 如果函数体的返回值只有一句,可以省略大括号(省略大括号会隐式返回这行代码的值)。
// 以下两种写法都有效,而且返回相应的值
let double = (x) => { return 2 * x; };
let triple = (x) => 3 * x;// 无效的写法
let multiply = (a, b) => return a * b;
  • 如果函数体不需要返回值,且只有一句话,可以给这个语句前面加一个void关键字。
// 最常见的就是调用一个函数
let fn = () => void doesNotReturn();

由于其更简洁的语法,箭头函数的一个用处就是简化回调函数。

// 普通函数写法
var result = arr.sort(function (a, b) {return a - b;
});// 箭头函数写法
var result = arr.sort((a, b) => a - b);

箭头函数没有自己的this

所有函数在执行时,会创建一个函数执行上下文,普通函数的执行上下文中会有一个变量this,而箭头函数没有,箭头函数不会创建自己的this对象,只会继承在自己作用域的上一层this。

var id = 'Global'// 箭头函数定义在全局作用域
let fun1 = () => {console.log(this.id)
}fun1() // 'Global'

输出:

可以⽤Babel理解⼀下箭头函数:

// ES6 
const obj = { getArrow() { return () => { console.log(this === obj); }; } 
}// 转化后的ES5
var obj = { getArrow: function getArrow() { var _this = this; return function () { console.log(_this === obj); }; } 
};

上面代码中,转换后的ES5版本清楚地说明了,箭头函数里没有自己的this,而是引用外层的this。

箭头函数的this不会改变

箭头函数没有自己的this,所以箭头函数中this的指向在它定义时就已经确定了,之后不会改变。

var name = 'GLOBAL';
var obj = {name: '南木元元',getName1: function(){console.log(this.name);},getName2: () => {console.log(this.name);}
};
obj.getName1();    // '南木元元'
obj.getName2();    // 'GLOBAL'

输出结果:

对象obj的方法b是使用箭头函数定义的,这个函数中的this就永远指向它定义时所处的全局执行环境中的this,即便这个函数是作为对象obj的方法调用,this依旧指向Window对象。所以其实定义对象的方法是不适合使用箭头函数的。

此外,call()、apply()、bind()等方法也不能改变箭头函数中this的指向。

var id = 'Global';
let fun1 = () => {console.log(this.id)
};
fun1();                     // 'Global'
// this的指向不会改变
fun1.call({id: 'Obj'});     // 'Global'
fun1.apply({id: 'Obj'});    // 'Global'
fun1.bind({id: 'Obj'})();   // 'Global'

输出结果:

箭头函数没有prototype属性

来看下面代码。

let fn = function(name) {console.log(name);
}
let fn2 = name => console.log(name);
console.log(fn.prototype);
console.dir(fn2.prototype);

输出结果:

箭头函数不能作为构造函数

上面说了,箭头函数没有自己的this,没有prototype属性,所以也就不能用作构造函数,即不可以对箭头函数使用new命令,否则会抛出错误。

let fn = (name, age) => {this.name = name;this.age = age;
}// 报错
let p = new fn('南木元元', 18);

输出结果:

为什么会这样呢?这其实跟new内部实现有关,new的实现步骤如下:

  • 创建一个新的空对象
  • 设置原型,将对象的原型设置为函数的prototype对象
  • 让函数的this指向这个对象,执行构造函数的代码
  • 返回新的对象
function myNew(constructor, ...args) {// 基于原型链 创建一个新对象,并且继承构造函数constructor的原型对象prototype上的属性let newObj = Object.create(constructor.prototype);// 执行构造函数,并让this指向这个新对象let res = constructor.apply(newObj, args); // 如果函数的执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象return typeof res === 'object' ? res: newObj;
}

上面的第二、三步,箭头函数都是没有办法执行的。

箭头函数不能使用arguments对象

arguments是一个对应于传递给函数的参数的类数组对象。

arguments是在所有普通函数中都可用的一个类数组对象,类数组不是数组,而是类似数组的对象它除了length属性和索引之外,不能调用数组的方法。

所以通常会使用Array.prototype.slice.call(arguments)/Array.from(arguments)/[...arguments]的方式,将它转换成一个数组。

let fn = function () {console.log(arguments);console.log(Array.prototype.slice.call(arguments));
}
fn('param1', 'param2');

输出结果:

箭头函数不可以使用arguments对象,该对象在函数体内不存在。

let fn = (name, age) => console.log(arguments);
// 报错
fn('南木元元', 18);

输出结果:

在箭头函数中访问arguments实际上获得的是它外层函数的arguments值。

let fn = function(name, age) {let fn2 = name => {console.log(arguments);}fn2();
}
fn('南木元元', 18);

 输出结果:

那么如果一定要用呢?可以用ES6中的rest参数代替。

let fn = (...args) => console.log(args);
fn('南木元元', 18);

输出结果:

上述代码使用了rest参数(形式为...变量名)获取函数的多余参数,这样就不需要使用arguments对象了。

箭头函数不能用作Generator函数

箭头函数内部不可以使用yield命令,因此箭头函数不能用作Generator函数。

let fn = function *() {yield '南木元元';
}
let p = fn();
console.log(p.next());

 输出:

let fn = *() => {yield '南木元元';
}
let p = fn();
console.log(p.next()); 

 输出:

箭头函数不适用的场景

  • 对象方法,且方法内部使用this

第一个场景上面提到过,定义对象的方法并且方法内部使用this时不适合用箭头函数。

var name = 'GLOBAL';
var obj = {name: '南木元元',getName: () => {console.log(this.name);}
};
obj.getName();    // 'GLOBAL'

上述代码中,调用obj.getName()方法时,如果是普通函数,该方法内部的this指向调用它的那个对象;如果写成上面那样的箭头函数,使得this指向了全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致getName箭头函数定义时的作用域就是全局作用域。

  • 需要动态this

第二个场合是需要动态this的时候,也不应使用箭头函数。

var button = document.getElementById('btn');
button.addEventListener('click', () => {console.log(this);    //由于使用了箭头函数,this会指向全局对象Window
});

上面代码运行时,点击按钮会报错,因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。

结语 

本文主要总结了箭头函数和普通函数的几大区别,箭头函数虽然语法简洁,但也有一些场合不适用,需要根据不同的场景选择使用合适的函数。

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏✍️评论支持一下博主~   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/224415.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10-让Java性能提升的JIT深度剖析

文章目录 JVM的语言无关性解释执行与JITC1、C2与Graal编译器C1编译器C2编译器 分层编译(了解即可)热点代码热点探测方法调用计数器回边计数器 编译优化技术方法内联锁消除标量替换逃逸分析技术逃逸分析的原理逃逸分析 JVM的语言无关性 跨语言(语言无关性&#xff0…

OpenHarmony之内核层解析~

OpenHarmony简介 技术架构 OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的组件…

平衡二叉树的构建(递归

目录 1.概念:2.特点:3.构建方法:4.代码:小结: 1.概念: 平衡二叉树(Balanced Binary Tree),也称为AVL树,是一种二叉树,它满足每个节点的左子树和右…

BDD - Python Behave Runner Script

BDD - Python Behave Runner Script 引言Runner Scriptsubprocess.run 调用 Behave 命令行调用 Behave 提供的 API behave_main 引言 通过终端命令执行 Behave 测试用例,有时 IDE 重启了,还得重新敲一遍命令,很是麻烦,说实话我都…

单例模式(C++实现)

RAII运用 只能在栈上创建对象 只能在堆上创建的对象 单例模式 设计模式 懒汉模式 解决线程安全 优化 饿汉模式 饿汉和懒汉的区别 线程安全与STL与其他锁

Hadoop入门学习笔记——四、MapReduce的框架配置和YARN的部署

视频课程地址:https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接:https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记(汇总) 目录 四、MapReduce的框架配置和YARN的部署4.1. 配置MapReduce…

微擎模块 出现Error: template source ‘common/message’ is not exist!解决方法

今天有会员反馈微课堂分销中心打不开,错误提示模板找不到:Error: template source ‘common/message’ is not exist!,看了下这模板应该微擎框架通用的,进公众号会员管理-会员中心网址居然也打不开,提示一样的错误&…

【hacker送书第11期】Python数据分析从入门到精通

探索数据世界,揭示未来趋势 《Python数据分析从入门到精通》是你掌握Python数据分析的理想选择。本书深入讲解核心工具如pandas、matplotlib和numpy,助您轻松处理和理解复杂数据。 通过matplotlib、seaborn和创新的pyecharts,本书呈现生动直…

5g消息-5G时代短信升级-富媒体智能交互-互联网新入口

在5G时代,运营商和各大手机厂商都在积极推进5G消息的商用,基于短信入口的富媒体消息应用在近两年得到快速发展,并在企业端形成了广泛应用。 作为5G时代的数字原生应用,5G消息支持用户通过文字、图片、音频、视频、位置等富媒体方式…

GIT具体配置步骤详解

GIT配置具体步骤如下 SDK 使用 Repo 工具管理,拉取 SDK 需要配置安装 Repo 工具。 Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workf…

SpringBoot集成opencc4j实现繁体中文转为简体中文

背景 繁体中文转为简体中文的需求非常常见,特别是在中文语境下的文本处理和翻译应用中。有很多现成的工具和库可以实现这个功能,比如 OpenCC 、 HanLP 等。从网上下载的 MySQL 版诗词数据库中的诗词数据都是繁体字,这里使用 SpringBoot 集成…

Apache Flink 进阶教程(七):网络流控及反压剖析

目录 前言 网络流控的概念与背景 为什么需要网络流控 网络流控的实现:静态限速 网络流控的实现:动态反馈/自动反压 案例一:Storm 反压实现 案例二:Spark Streaming 反压实现 疑问:为什么 Flink(bef…

物联网产品设计,聊聊设备OTA的升级

物联网产品设计部分的OTA设备固件是一个非常重要的部分,能够实现升级用户服务、保障系统安全等功能。 在迅速变化和发展的物联网市场,新的产品需求不断涌现,因此对于智能硬件设备的更新需求就变得空前高涨,设备不再像传统设备一样…

unity HoloLens2开发,使用Vuforia识别实体 触发交互(二)(有dome)

提示:文章有错误的地方,还望诸位大神不吝指教! 文章目录 前言一、打包到HoloLens二、Vuforia相关1.配置识别框2.制作一个半透明识别框:3.设置如下4.问题 四 HoloLens2 问题总结 前言 我使用的utniy 版本:Unity 2021.3…

产品原型设计软件 Axure RP 9 mac支持多人写作设计

axure rp 9 mac是一款产品原型设计软件,它可以让你在上面任意构建草图、框线图、流程图以及产品模型,还能够注释一些重要地方,axure rp汉化版可支持同时多人写作设计和版本管理控制,这款交互式原型设计工具可以帮助设计者制作出高…

Jenkins自动化构建打包,部署

1.环境准备 上传jdk,maven和tomcat的包,解压到/usr/local下并配置环境变量。 配置jdk [rootserver04 ~]# vim /etc/profile.d/java.sh JAVA_HOME/usr/local/java export PATH$JAVA_HOME/bin:$PATH##加载环境变量 [rootserver04 ~]# source /etc/profi…

由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求。

问题描述: 由于被认为是客户端对错误(例如:畸形的请求语法、无效的请求信息帧或者虚拟的请求路由),服务器无法或不会处理当前请求。 在实现向数据库中添加记录时,请求发送无效,参数也未传递到控…

HAL库的常用库函数(根据学习而更新)

目录 一、常用的GPIO相关HAL库函数 1、GPIO的初始化 2、配置GPIO引脚输出电平 3、切换指定引脚的电平,电平的翻转 4、读取指定GPIO引脚的电平 5、结构体 GPIO_InitTypeDef (引脚)定义: 6、高低电平的表示 7、延时函数&…

如何使用内网穿透工具实现Java远程连接本地Elasticsearch搜索分析引擎

文章目录 前言1. Windows 安装 Cpolar2. 创建Elasticsearch公网连接地址3. 远程连接Elasticsearch4. 设置固定二级子域名 前言 简单几步,结合Cpolar 内网穿透工具实现Java 远程连接操作本地分布式搜索和数据分析引擎Elasticsearch。 Cpolar内网穿透提供了更高的安全性和隐私保…

【计算机视觉中的多视图几何系列】深入浅出理解针孔相机模型

温故而知新,可以为师矣! 一、参考资料 《计算机视觉中的多视图几何-第五章》-Richard Hartley, Andrew Zisserman. 二、针孔模型相关介绍 1. 重要概念 1.1 投影中心/摄像机中心/光心 投影中心称为摄像机中心,也称为光心。投影中心位于一…