ES6学习 第七章 函数的扩展
前言
本章介绍函数的扩展。有些不常用的知识了解即可。
本章原文链接:函数的扩展。
函数参数的默认值
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
当函数形参没有被赋值时,才会将默认值赋值给函数参数。
// 默认值直接写在行参后面
function sampleFn(sample = 0, sample1 = 0) {
return sample + sample1;
}
注意:
- 参数变量是默认声明的,所以不能用
let或const再次声明。 - 使用参数默认值时,函数不能有同名参数。
- 参数默认值是惰性求值的。
- 函数的默认值指定后,函数
length属性返回的是没有指定默认值的参数的个数。 - 参数的默认值一旦设定,函数进行声明初始化时,参数会形成一个单独的作用域(context)。
// 默认值直接写在行参后面
function sampleFn(sample = 0, sample1 = 0,sample = 1) { // 不能有同名参数
let sample = 1; // 不能再次声明
return sample + sample1;
}
注意:通常情况下,定义了默认值的参数,应该是函数的尾参数。也就是放在最后面。
解构赋值默认值
// 函数的默认值与结构赋值的默认值可以结合使用
function sampleFn({ sample = 0, sample1 = 0 } = {}) { // 函数参数默认值
return sample + sample1;
}
console.log(sampleFn({ sample: 23, sample1: 33 })); // 56 参数需对应解构赋值的类型
作用域
当函数参数设置了默认值,函数进行声明初始化时,函数参数会生成一个单独的作用域,等到初始化结束,该作用域就会消失。而且该行为只在函数参数指定了默认值才会出现。
let sample = 1;
/*
在声明的时候出现单独作用域
在这个作用域中,变量没有定义,于是指向外层变量
函数调用时,函数内部变量影响不到默认值变量
*/
function sampleFn(sample1 = sample) {
let sample = 2;
console.log(sample1);
return sample1;
}
sampleFn() // 1
rest 参数
ES6 引入 **rest 参数 **,用于获取函数的多余参数。
arguments 对象是类数组,rest 参数是真正的数组。
形式为:...变量名,函数的最后一个命名参数以...为前缀。
// 下面例子中 ...values 为 rest参数 ,用于获取多余参数
const sample = function (title, ...values) {
let sample = values.filter(
(item) => {
return item % 2 === 0;
}
)
return (title + sample);
}
console.log(sample("求偶数", 1, 2, 6, 2, 1)); // 求偶数 2, 6, 2
注意:rest参数 只能是函数的最后一个参数,函数的length不包括rest参数
严格模式
在JavaScript中,只要在函数中的严格模式,会作用于函数参数和函数体。
ES2016 规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
function sample() { // 参数使用默认值、解构赋值、扩展运算符
'use strict'; // 开启严格模式
}
name 属性
函数的name属性,返回该函数的函数名。
function sample() { };
let sample1 = function () { };
function sample2() {};
console.log(sample.name); // sample
console.log(sample1.name); // sample1
// bound sample2 使用了 bind 方法,输出会有bound前缀
console.log(sample2.bind({}).name);
console.log((new Function).name); // anonymous 构造函数的name值为 anonymous
箭头函数
简单介绍
ES 6 新增一种函数定义方法,使用箭头连接参数列与函数题。
箭头函数相当于匿名函数,并且简化了函数定义,箭头函数没有prototype。
// 普通函数
let sample = function (item) {
return item;
};
// 上面函数等同于下面函数
// 使用箭头函数
let sample = (item) => { return item}; // 箭头函数
箭头函数简写
没错,箭头函数还可以简写
- 当参数只有一个时,可以省略箭头左边的括号,但没有参数时,括号不可以省略。
- 当函数体只有一个表达式时,可省略箭头右边的大括号,但同时必须省略
return语句 并写在一行。 - 当函数体分多于一条语句,就要使用大括号将它们括起来,并且使用
return语句返回。
// 下面几种函数写法都相同
let sample = function (item) {
return item;
};
let sample = (item) => { return item}; // 箭头函数 不省略
let sample = item => { return item}; // 省略左边圆括号
let sample = (item) => item; // 省略右边大括号和 return
let sample = item => item; // 省略左边圆括号和右边花括号和return
// 如果不需要返回值的特殊情况
let sample = item => void item;
console.log(sample()); // undefined
注意点
- 箭头函数 的
This默认指向定义它的作用域的This。 - 箭头函数 不能用作构造函数。
- 箭头函数 不可以使用
arguments对象,该对象在函数体内不存在。 - 箭头函数 不可以使用
yield命令,也就不能作为 Generator 函数。
箭头函数的this
箭头函数 会继承自己定义时所处的作用域链上一层的this。
箭头函数 this在定义的时候已经确定了,所以箭头函数this不会改变。
使用 call() 或 apply() 方法时,也不能重新给箭头函数绑定this,bing()方法无效。
window.sample = "window 内 ";
function sampleFn() {
let thiz = this;
let sample = "sampleFn 内 ";
let sampleObj = {
sample: "sampleObj 内 ",
// 普通函数
sampleFn1: function () {
console.log(thiz === this);
console.log(this.sample);
},
// 箭头函数
sampleFn2: () => {
// 箭头函数的作用域为 sampleObj 上一层为 sampleFn
console.log(thiz === this); //箭头函数的 this
console.log(this.sample);
}
}
sampleObj.sampleFn1(); // false, sampleObj 内
sampleObj.sampleFn2(); // true, window 内
}
sampleFn();
尾调用优化
有两个概念
尾调用
尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数。尾递归
函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
ES6 明确规定,所有 ECMAScript 的实现,都必须部署“尾调用优化”。
这就是说,ES6 中只要使用尾递归,就不会发生栈溢出(或者层层递归造成的超时),相对节省内存。
这是什么意思呢?
尾调用的作用,在原文中是这样写的:
我们知道,函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一个C的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。
尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。
换种方式解释吧
函数被调用的时候会有函数执行上下文被压入执行栈中,直到函数执行结束,对应的执行上下文才会出栈。
在函数A的内部调用函数B,如果函数B中有对函数A中变量的引用,那么函数A即使执行结束对应的执行上下文也无法出栈,如果函数B内部还有调用函数C那么要等函数C执行完,函数A、B对应的执行上下文才能出栈,以此类推,执行栈中要上一个函数(内层函数)的执行上下文,这就是尾调用优化。
// 尾递归
function sampleFn(sample) {
if (sample <= 1) return 1;
return sampleFn(sample - 1) + sample;
}
sampleFn(2);
注意 :
- 当内层函数没有用到外层函数的内部变量的时候才可以进行尾调用优化。
- 目前只有 Safari 浏览器支持尾调用优化,Chrome 和 Firefox 都不支持。
ES 6 的小修改
函数参数尾逗号
ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。
这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。
function sampleFn(
sample1,
sample2,
sample3, // 可以在最后一个参数后面加 逗号 ','
) {}
toString()修改
Function.prototype.toString()
ES2019 对函数实例的toString()方法做出了修改。明确要求返回一模一样的原始代码。
toString()方法返回函数代码本身,ES6前会省略注释和空格。
function sampleFn() {
// 注释
}
let sample = sampleFn.toString();
console.log(sample);
//输出 完全一样的原始代码,包括空格与注释
/*
function sampleFn() {
// 注释
}
*/
catch 修改
ES2019 改变了catch语句后面必须携带参数的要求。允许catch语句省略参数。
try {
// ...
} catch { // 不带参数
// ...
}
ES6学习 第七章 函数的扩展的更多相关文章
- ES6学习 第五章 正则的扩展
前言 本章介绍正则的扩展.有些不常用的知识了解即可. 本章原文链接:正则的扩展 RegExp 构造函数 从 ES6 开始,如果RegExp构造函数第一个参数是一个正则对象,并且第二个标志存在且为标志参 ...
- ES6学习笔记<三> 生成器函数与yield
为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...
- Go语言学习笔记七: 函数
Go语言学习笔记七: 函数 Go语言有函数还有方法,神奇不.这有点像python了. 函数定义 func function_name( [parameter list] ) [return_types ...
- C#高级编程 (第六版) 学习 第七章:委托和事件
第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...
- Java基础知识二次学习--第七章 容器
第七章 容器 时间:2017年4月27日15:08:30 章节:07章01节~07章04节 视频长度:20:21 +12:38 +3:55 +2:57 内容:容器API 心得: Java API ...
- 流畅的python第七章函数装饰器和闭包学习记录
本章讨论的话题 python如何计算装饰器句法 python如何判断变量是不是局部的(通过函数内部是否给变量赋值过来判断是否是局部变量) 闭包存在的原因和工作原理(闭包是一种函数,它会保留定义函数时存 ...
- ES6新特性3:函数的扩展
本文摘自ECMAScript6入门,转载请注明出处. 一.函数参数默认值 1. ES6允许为函数的参数设置默认值,即直接写在参数定义的后面. function log(x, y = 'World') ...
- es6学习笔记10--箭头函数
基本用法 ES6允许使用“箭头”(=>)定义函数. var f = v => v; 上面的箭头函数等同于: var f = function(v) { return v; }; 如果箭头函 ...
- ES6学习笔记七:生成器与异步操作
一:Generator Generator 函数是一个普通函数,但是有两个特征.一是,function关键字与函数名之间有一个星号:二是,函数体内部使用yield表达式,输出不同的内部状态. 执行 G ...
- ES6系列_7之箭头函数和扩展
1.默认值 在ES6中给我们增加了默认值的操作相关代码如下: function add(a,b=1){ return a+b; } console.log(add(1)); 可以看到现在只需要传递一个 ...
随机推荐
- Mysql 中 not in 的查询优化
本文为博主原创,转载请注明出处: 最近做性能优化时,通过开启 MySQL 的慢日志查询配置,发现 有一条慢sql,在这里记录下分析和优化的过程. 该慢 sql 如下: select id from f ...
- c#.net 6 实现简单爬虫几行代码实现百度搜索
使用selenium封装的简单使用工具包 Gitee:SeleniumUtil: Selenium简化工具包,包含三个主流浏览器的一些基本操作 (gitee.com) 第一步安装爬虫工具: 在程序包管 ...
- SV概述
System Verilog概述 路科验证视频,B站可看(补充一下知识) 学习SV之前,最好有Verilog基础 SV诞生 SV发展历史 Verilog - 偏向于设计 System Verilog ...
- 永久激活Windows10专业版及其它版本【亲测有效2022-03-16,两种方式】
前言 小编最近使用公司的电脑,开始出现让你激活的提示,而且每次开机都会弹出来,小编忍住了:但是过不了半个月开始给你在桌面上显示了,一直显示和水印一样.小编忍无可忍,必须找个办法给你消灭掉!!,于是小编 ...
- 【Gui-Guider】安装后运行模拟器报 JAVA 错误
运行模拟器出错 上述错误是因为需要JAVA环境 JAVA 环境下载网址 https://www.oracle.com/java/technologies/javase-jdk16-downloads. ...
- Shell-函数-function
- 【ES系列】(一)简介与安装
首发博客地址 首发博客地址 系列文章地址 教学视频 为什么要学习 ES? 强大的全文搜索和检索功能:Elasticsearch 是一个开源的分布式搜索和分析引擎,使用倒排索引和分布式计算等技术,提供了 ...
- [转帖]pyinstaller实现将python程序打包成exe文件
https://www.cnblogs.com/blogzyq/p/13939739.html 如果我们想要在一个没有python以及很多库环境的电脑上使用我们的小程序该怎么办呢? 我们想到,在Win ...
- [转帖]TIDB-TIDB节点磁盘已满报警
一.背景 今日突然收到tidb节点的磁盘报警,磁盘容量已经超过了80%,但是tidb是不放数据的,磁盘怎么会满,这里就需要排查了 二.问题排查 解决步骤 1.df -h查看哪里占用磁盘比较多,然后通过 ...
- 【转帖】TCP内核参数
https://www.cnblogs.com/chia/p/7799231.html tcp_syn_retries :INTEGER默认值是5对于一个新建连接,内核要发送多少个 SYN 连接请求才 ...