【05】ES6:函数的扩展
一、函数参数的默认值
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
1、基本用法
默认值的生效条件
不传参数,或者明确的传递 undefined 作为参数,只有这两种情况下,默认值才会生效。
注意:null 就是 null,不会使用默认值。
// ES6 之前的默认值实现方式
const log = (x, y) => {// typeof类型检测:返回表示当前数据类型的字符串if (typeof y === 'undefined') {y = 'world'}console.log(x, y)
}log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
// ES6 默认值实现方式
function log(x, y = 'World') {console.log(x, y)
}log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
默认值的一些规则
参数变量是默认声明的,所以不能用let或const再次声明。
function foo(x = 5) {let x = 1 // errorconst x = 2 // error
}
使用参数默认值时,函数不能有同名参数。
// 不报错
function foo(x, x, y) {// ...
}// 报错 SyntaxError: Duplicate parameter name not allowed in this context
function foo(x, x, y = 1) {// ...
}
参数默认值是惰性求值的。参数默认值不是传值的,而是每次都重新计算默认值表达式的值。
let x = 99
function foo(p = x + 1) {console.log(p)
}foo() // 100x = 100
foo() // 101
2、与解构赋值默认值结合使用
函数参数默认值 可以与 解构赋值的默认值,结合起来使用。通过给函数参数设置默认值,可以避免在没有提供参数时出现错误。
// 只使用对象的解构赋值默认值
function foo({ x, y = 5 }) {console.log(x, y)
}foo({}) // undefined 5
foo({ x: 1 }) // 1 5
foo({ x: 1, y: 2 }) // 1 2
// 函数 foo()调用时没提供参数,变量 x 和 y 就不会生成,从而报错
foo() // TypeError: Cannot read property 'x' of undefined// -------------------------------------------// 使用对象的解构赋值默认值 + 函数参数的默认值
function foo({ x, y = 5 } = {}) {console.log(x, y)
}foo() // undefined 5
// 只使用对象的解构赋值默认值
function fetch(url, { body = '', method = 'GET', headers = {} }) {console.log(method)
}fetch('http://example.com', {}) // 'GET'
fetch('http://example.com') // 报错// --------------------------------------------------// 使用对象的解构赋值默认值 + 函数参数的默认值
function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {console.log(method)
}fetch('http://example.com') // 'GET'
注意,函数参数的默认值生效以后,参数解构赋值依然会进行。
// 参数默认值 { a: 'hello' } 生效;进行解构赋值,从而触发参数变量 b 的默认值生效。
function f({ a, b = 'world' } = { a: 'hello' }) {console.log(b)
}f() // world// 解构赋值的默认值只在属性值为 undefined 时才会生效
function f({ a, b = 'world' } = { b: 'hello' }) {console.log(b)
}f() // hello
3、参数默认值的位置
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
// 例一
function f(x = 1, y) {return [x, y]
}f() // [1, undefined]
f(2) // [2, undefined]
f(, 1) // 报错
f(undefined, 1) // [1, 1]// 例二
function f(x, y = 5, z) {return [x, y, z]
}f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 报错
f(1, undefined, 2) // [1, 5, 2]
上面代码中,有默认值的参数都不是尾参数。这时,无法只省略该参数,而不省略它后面的参数,除非显式输入 undefined。
如果传入 undefined,将触发该参数等于默认值,null 则没有这个效果。
function foo(x = 5, y = 6) {console.log(x, y)
}foo(undefined, null) // 5 null
4、函数的 length 属性
函数的 length 属性,等于该函数预期传入的参数个数。
当函数指定默认值后,length 属性将失真。将返回没有指定默认值的参数个数,如果设置了默认值的参数不是尾参数,那么 length 属性也不再计入后面的参数了。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2(function(...args) {}).length // 0(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
5、应用
利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。
function throwIfMissing() {throw new Error('Missing parameter')
}function foo(mustBeProvided = throwIfMissing()) {return mustBeProvided
}foo() // Error: Missing parameter
上面代码的 foo 函数,如果调用的时候没有参数,就会调用默认值 throwIfMissing 函数,从而抛出一个错误。
从上面代码还可以看到,参数 mustBeProvided 的默认值等于 throwIfMissing 函数的运行结果(注意函数名 throwIfMissing 之后有一对圆括号),这表明参数的默认值不是在定义时执行,而是在运行时执行。如果参数已经赋值,默认值中的函数就不会运行。
另外,可以将参数默认值设为 undefined,表明这个参数是可以省略的。
function foo(optional = undefined) { ··· }
二、reset 参数(…不定参数)
ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用 arguments 对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {let sum = 0for (var val of values) {sum += val}return sum
}add(2, 5, 3) // 10
// arguments 变量的写法
function sortNumbers() {// arguments 为类数组对象,需先使用 Array.from 转换为数组return Array.from(arguments).sort()
}// rest 参数的写法 (reset 参数为真正的数组)
const sortNumbers = (...numbers) => numbers.sort()
注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
// 报错
function f(a, ...b, c) {// ...
}
函数的 length 属性,不包括 rest 参数。
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
三、箭头函数
ES6 规定了可以使用 “箭头” => 来定义一个函数,语法更加简洁。它没有自己的 this、arguments、super 或 new.target,箭头函数表达式更适用于那些本来需要匿名函数的地方,但它不能用作构造函数。
1、基本使用
普通函数
function 函数名() {}const 变量名 = function () {}
箭头函数
(参数) => {函数体}const 变量名 = () => {}
// 基本语法
const add = (x, y) => {return x + y
}// 有且只有一个参数,()可以省略
const add = x => {return x + 1
}// 有且只有一条语句,且为 returen 语句,{} 和 return 可以省略
const add = (x, y) => x + y// return 为对象时,对象外需要加 ()
const add = (x, y) => {return {value: x + y}
}
const add = (x, y) => ({ value: x + y })
2、函数 this 指向
es5 中的 this 指向
函数 this 的取值,是在函数执行的过程中确定的,不是在函数定义时确定的。
(1) 作为普通函数被调用,this 指向 window
(2) 作为对象方法被调用时,this 指向当前对象
(3) 在构造函数中(es5, es6的class方法),this 指向通过构造函数创建的实例对象
(5) 定时器中函数的 this 指向 window,定时器中函数相当于普通函数被调用(setTimeout | setInterval)
es6 中箭头函数的 this 指向
箭头函数中的 this 是在定义的时候绑定的,this 取上级作用域的 this,箭头函数本身不会决定 this 的值。
call、 apply 、 bind
fn.call(this, …params) 和 fn.apply(this, [params]) 都是用来改变函数的this指向
区别是传参不同,call()接受的是列表,apply()接受的是数组
fn.bind(this, params) 方法也是用来改变函数this指向,但是不会立即执行,而是返回一个新函数
3、不适用箭头函数的场景
作为构造函数
因为箭头函数没有 this,而构造函数的核心就是 this。
需要 this 指向调用对象的时候
因为箭头函数没有 this,所以如果箭头函数中出现了 this,那么这个 this 就是外层的!
给事件绑定方法时,比如说通过 addEventListener 给某个事件绑定方法,如果使用箭头函数,此时 this,会指向父级的this window
在定义某个对象的方法时,不可以使用箭头函数
在 vue 的 methods 中的方法,也不可以使用箭头函数,会使 this 指向的不是当前的vm实例,发生错误
需要使用 arguments 的时候
箭头函数没有 arguments。(这个问题有替代解决方案:不定参数)
没有原型
由于箭头函数不能用作构造函数,它们也没有自己的原型。因此,不能使用 prototype 属性来添加新方法。
不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数
四、函数参数的尾逗号
ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。
此前,函数定义和调用时,都不允许最后一个参数后面出现逗号。
function clownsEverywhere(param1,param2
) { /* ... */ }clownsEverywhere('foo','bar'
)
上面代码中,如果在 param2 或 bar 后面加一个逗号,就会报错。
如果像上面这样,将参数写成多行(即每个参数占据一行),以后修改代码的时候,想为函数 clownsEverywhere 添加第三个参数,或者调整参数的次序,就势必要在原来最后一个参数后面添加一个逗号。这对于版本管理系统来说,就会显示添加逗号的那一行也发生了变动。这看上去有点冗余,因此新的语法允许定义和调用时,尾部直接有一个逗号。
function clownsEverywhere(param1,param2,
) { /* ... */ }clownsEverywhere('foo','bar',
)
这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。
五、catch 命令的参数省略
JavaScript 语言的 try…catch 结构,以前明确要求 catch 命令后面必须跟参数,接受 try 代码块抛出的错误对象。
try {// ...
} catch (err) {// 处理错误
}
上面代码中,catch命令后面带有参数err。
很多时候,catch代码块可能用不到这个参数。但是,为了保证语法正确,还是必须写。ES2019 做出了改变,允许catch语句省略参数。
try {// ...
} catch {// ...
}
相关文章:
【05】ES6:函数的扩展
一、函数参数的默认值 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。 1、基本用法 默认值的生效条件 不传参数,或者明确的传递 undefined 作为参数,只有这两种情况下,默认值才会生效。 注意:null 就…...
Ubuntu20.04安装搜狗输入法
1、安装包下载 搜狗输入法linux-首页搜狗输入法for linux—支持全拼、简拼、模糊音、云输入、皮肤、中英混输https://shurufa.sogou.com/linux点击立即下载,根据自己的硬件选择deb安装包。 2、输入法安装 当第一步完成以后,页面会自动跳转至搜狗的安装…...
linux的基础命令
文章目录 linux的基础命令一、linux的目录结构(一)Linux路径的描述方式 二、Linux命令入门(一)Linux命令基础格式 三、ls命令(一)HOME目录和工作目录(二)ls命令的参数1.ls命令的-a选…...
linux查询某个进程使用的内存量
linux查询某个进程使用的内存量 查进程用的内存,查看进程占用的内存量,centos查询内存使用 查某个进程id使用的内存量 ps -p 24450 -o rss | awk {print int($1/1024)"MB"} 该命令的含义是: ps -p 24450: 查找进程ID为24450的进…...
list的总结
目录 1.什么是list 1.1list 的优势和劣势 优势: 劣势: 2.构造函数 2.1 default (1) 2.2 fill (2) 2.3 range (3) 2.4 copy (4) 3.list iterator的使用 3.1. begin() 3.2. end() 3.3迭代器遍历 4. list容量函数 4.1. empty() 4.2. siz…...
c语言数字转圈
数字转圈 题干输入整数 N(1≤N≤9),输出如下 N 阶方阵。 若输入5显示如下方阵: * 1** 2** 3** 4** 5* *16**17**18**19** 6* *15**24**25**20** 7* *14**23**22**21** 8* *13**12**11**10** 9*输入样例3输出样例* 1*…...
Apache Superset数据分析平台如何实现公网实时远程访问数据【内网穿透】
文章目录 前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透,实现公网访问3. 设置固定连接公网地址 前言 Superset是一款由中国知名科技公司开源的“现代化的…...
HarmonyOS应用开发实战—登录页面【ArkTS】
文章目录 本页面实战效果预览图一.HarmonyOS应用开发1.1HarmonyOS 详解1.2 ArkTS详解二.HarmonyOS应用开发实战—登录页面【ArkTS】2.1 ArkTS页面源码2.2 代码解析2.3 心得本页面实战效果预览图 一.HarmonyOS应用开发 1.1HarmonyOS 详解 HarmonyOS(鸿蒙操作系统)是华为公司…...
@RequestMapping
目录 作用: 位置: 属性 1.value 2.method 3.params 4.header 作用: 该注解是一个用来处理请求地址映射的注解。 位置: 可用于映射一个请求或一个方法,可以用在类或方法上。 用于方法上,表示在类的…...
操作系统 应用题 例题+参考答案(考研真题)
1.(考研真题)一个多道批处理系统中仅有P1和P2两个作业,P2比P1晚5ms到达,它们的计算和I/O操作顺序如下。 P1:计算60ms,I/O 80ms,计算20ms。 P2:计算120ms,I/O 40ms&…...
免费获取GPT-4的五种工具
不可否认,由OpenAI带来的GPT-4已是全球最受欢迎的、功能最强大的大语言模型(LLM)之一。大多数人都需要使用ChatGPT Plus的订阅服务去访问GPT-4。为此,他们通常需要每月支付20美元。那么问题来了,如果您不想每月有这笔支…...
XTU OJ 1146 矩阵乘法学习笔记
原题 题目描述 给你两个矩阵A(n*k),B(k*m),请求A*B。 输入 第一行是一个整数K,表示样例的个数。 每个样例包含两个矩阵A和B。 每个矩阵的第一行是两个整数n,m,(1≤n,m≤10)表示矩阵的行和列 以后的n行,每行m个整数,每个整数的绝对值不超过…...
基于官方YOLOv4开发构建目标检测模型超详细实战教程【以自建缺陷检测数据集为例】
本文是关于基于YOLOv4开发构建目标检测模型的超详细实战教程,超详细实战教程相关的博文在前文有相应的系列,感兴趣的话可以自行移步阅读即可:《基于yolov7开发实践实例分割模型超详细教程》 《YOLOv7基于自己的数据集从零构建模型完整训练、…...
1、Docker概述与安装
相关资源网站: ● docker官网:http://www.docker.com ● Docker Hub仓库官网: https://hub.docker.com/ 注意,如果只是想看Docker的安装,可以直接往下拉跳转到Docker架构与安装章节下的Docker具体安装步骤,一步步带你安…...
论文笔记——FasterNet
为了设计快速神经网络,许多工作都集中在减少浮点运算(FLOPs)的数量上。然而,作者观察到FLOPs的这种减少不一定会带来延迟的类似程度的减少。这主要源于每秒低浮点运算(FLOPS)效率低下。 为了实现更快的网络,作者重新回顾了FLOPs的运算符,并证明了如此低的FLOPS主要是由…...
计算机组成原理-固态硬盘SSD
文章目录 总览机械硬盘vs固态硬盘固态硬盘的结构固态硬盘与机械硬盘相比的特点磨损均衡技术例题 总览 机械硬盘vs固态硬盘 固态硬盘采用闪存技术,是电可擦除ROM 下图右边黑色的块块就是一块一块的闪存芯片 固态硬盘的结构 块大小16KB~512KB 页大小512B~4KB 对固…...
Electron+VUE3开发简版的编辑器【文件预览】
简版编辑器的功能主要是: 打开对话框,选择文件后台读取文件文件前端展示文件内容。主要技术栈是VUE3、Electron和Nodejs,VUE3做页面交互,Electron提供一个可执行Nodejs的环境以及支撑整个应用的环境,nodeJS负责读取文件内容。 环境配置、安装依赖这些步骤就不再叙述了。 …...
docker、elasticsearch8、springboot3集成备忘
目录 一、背景 二、安装docker 三、下载安装elasticsearch 四、下载安装elasticsearch-head 五、springboot集成elasticsearch 一、背景 前两年研究了一段时间elasticsearch,当时也是网上找了很多资料,最后解决个各种问题可以在springboot上运行了…...
【Lombok使用详解】
目录 前言:注解速查1.Lombok概念2.安装Lombok3. 使用Lombok3.1 😊Data3.2 GetterSetter3.3 NonNull3.4 Synchronized3.5 ToString:自动生成toString()方法3.6 Cleanup3.7 EqualsAndHashCode 前言:注解速查 NonNull : 用在成员方法…...
Tars框架 Tars-Go 学习
Tars 框架安装 网上安装教程比较多,官方可以参数这个 TARS官方文档 (tarsyun.com) 本文主要介绍部署应用。 安装完成后Tars 界面 增加应用amc 部署申请 amc.GoTestServer.GoTestObj 名称不知道的可以参考自己创建的app config 点击刷新可以看到自己部署的应用 服…...
告别手动配置!用RMServer Aid一键搞定RoboMaster裁判系统服务器(附MySQL 8.0.28集成版)
从零到一:RoboMaster裁判系统服务器自动化搭建全攻略 每次RoboMaster赛季来临,参赛队伍最头疼的莫过于裁判系统服务器的搭建。传统的手动配置方式不仅耗时费力,还容易因为网络设置、MySQL配置等问题导致比赛现场出现意外。我曾见过一支队伍因…...
手把手教你用CANoe/CANalyzer模拟UDS诊断服务(ISO 14229实战)
实战指南:用CANoe/CANalyzer构建UDS诊断仿真环境 在汽车电子开发领域,诊断功能验证是确保ECU可靠性的关键环节。想象一下,当你面对一个全新的ECU模块,需要快速验证其诊断协议合规性,却苦于没有实车环境或待测硬件尚未就…...
从仿真到综合:手把手拆解Verilog中always@(*)与assign的真实差异(附Testbench调试技巧)
从仿真到综合:手把手拆解Verilog中always(*)与assign的真实差异(附Testbench调试技巧) 在数字IC设计领域,Verilog作为硬件描述语言的代表,其语法细节往往直接影响设计质量。always(*)和assign作为描述组合逻辑的两种主…...
OkHttp3实战:除了GET和POST,你还能用它轻松搞定文件上传和Session保持
OkHttp3实战:解锁文件上传与Session保持的高级技巧 在移动应用开发中,网络请求是几乎所有功能的基础支撑。OkHttp3作为Android平台上最受欢迎的HTTP客户端库之一,其简洁的API设计和强大的功能让开发者能够轻松处理各种网络请求场景。但很多开…...
从‘猫鼠游戏’到‘艺术创作’:用StyleGAN2-ADA的实战案例,聊聊不同GAN变体损失函数的设计哲学
从博弈论到艺术革命:StyleGAN2-ADA如何用损失函数重塑图像生成 想象一下,你正在教两个学生画画——一个负责鉴别画作真伪(判别器),另一个则试图伪造名画(生成器)。最初,这场教学就像…...
不花一分冤枉米!MedPeer科研工具最优解
打开会员页面十几款套餐摆面前,不知道哪款匹配自己的需求,怕买错了浪费钱,买便宜了又不够用?作为一直在用MedPeer的老科研人,我整理了这篇全套餐梳理,帮不同需求、不同领域的科研人快速选到最划算的那一款&…...
RH850 CSIH SPI驱动避坑指南:从寄存器配置到中断处理的实战经验
RH850 CSIH SPI驱动避坑指南:从寄存器配置到中断处理的实战经验 在嵌入式开发领域,RH850系列微控制器的CSIH SPI模块因其高性能和灵活性备受工程师青睐。然而,其复杂的寄存器配置和中断处理机制常常成为项目开发中的"拦路虎"。本文…...
深入FM33FR0xx的GPIO高级功能:用FL库实现外部中断与低功耗唤醒
深入FM33FR0xx的GPIO高级功能:用FL库实现外部中断与低功耗唤醒 在嵌入式系统设计中,GPIO(通用输入输出)接口的功能远不止简单的电平控制。对于复旦微FM33FR0xx系列MCU而言,其GPIO模块集成了外部中断触发和低功耗唤醒两…...
短视频智能获客系统完整版:支持抖音/快手/视频号,含管理后台+手机端
温馨提示:文末有资源获取方式短视频赛道越来越卷,光靠人工剪辑发布已经跟不上节奏了。最近把一套能同时管理多个平台账号的系统跑通了,整理一下核心功能,给有需要的朋友参考。一、多平台统一管理支持抖音、快手、视频号、小红书、…...
用JSBSim和VS2019搭建你自己的简易飞行仿真器(从模型加载到数据获取)
用JSBSim和VS2019构建高交互性飞行仿真器的实战指南 飞行仿真技术一直是航空航天领域的重要工具,从专业训练到娱乐游戏,这项技术正在变得越来越普及。对于开发者而言,构建自己的飞行仿真器不仅能深入理解飞行力学原理,还能为更复杂…...
