当前位置:网站首页>【ES6】函数的扩展
【ES6】函数的扩展
2022-04-21 21:56:00 【小沈曰】
1、函数参数的默认值
基本用法
在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
function log(x, y){
y = y || 'world'
console.log(x,y)
}
log('hello') //hello world
log('hello', 'china') //hello china
log('hello', '') //hello world
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, y = 5}){
console.log(x, y)
}
foo({
}) //undefined 5
foo({
x: 1 }) //1 5
foo({
x: 1, y: 2}) //1 2
foo() //报错
function foo2({
x, y = 5} = {
}){
console.log(x, y)
}
foo() //undefined 5
参数默认值的位置
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
function fn(x = 1, y){
return [x, y]
}
fn() //[1, undefined]
fn(2) //[2, undefined]
fn(, 1) //报错
fn(undefined, 1) //[1,1]
函数的length属性
指定了默认值后,函数的length属性,将返回没有指定默认值的参数个数,如果遇到默认值,直接停止返回长度,也就是指统计第一次出现默认值之前的参数个数
(function(a) {
}).length //1
(function(a = 5) {
}).length //0
(function(a,b,c = 5) {
}).length //2
作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时是不会出现的。
var x = 1
function fn(x, y = x){
console.log(y)
}
fn(2) //2
解释: 参数y的默认值等于变量x。调用函数fn时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2
再看下面的例子:
let x = 1
function fn(y = x){
let x = 2
console.log(y)
}
fn() //1
解释: 函数调用时,参数y = x 形成一个单独的作用域,这个作用域里面,变量x 本身没有定义,所以指向外层的全局变量x。函数调用时,函数体内部的局部变量 x 影响不到默认值变量 x,如果此时全局变量x不存在就会报错。
2、rest参数
ES6引入rest参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中(实际上是扩展运算符的逆运算)
function add(...val){
let sum = 0
for(var v of val){
sum += v
}
return sum
}
add(2,5,3) //10
arguments对象不是数组,而是一个类数组对象,所以为了使用数组方法,必须使用Array.prototype.slice.call先将其转为数组。rest参数就不存在这个问题了,他就是一个真正的数组。
3、严格模式
从ES5开始,函数内部可以设定为严格模式
function todo(a,b){
'use strict'
//...
}
ES6做了一点修改,规定只要函数参数使用了默认值,解构赋值,或者扩展运算符,那么函数内部就不能显示设定为严格模式,否则会报错
//报错
function todo (a, b, c = 1){
use 'strict'
//...
}
4、name属性
函数的name属性,返回该函数的函数名
function foo() {
}
foo.name // 'foo'
注意 ES6对这个属性的行为做出了一些修改,如果将一个匿名函数赋值给一个变量,ES5的name属性,会返回空字符串,而ES6的name属性会返回实际的函数名
var fn = function () {
}
//es5
fn.name // ''
//es6
fn.name // 'fn'
如果将一个具名函数赋值给一个变量,ES5和ES6的name属性都会返回这个具名函数原本的名字
const bar = function baz() {
}
//es5
bar.name // 'baz'
//es6
bar.name // 'baz'
Function构造函数返回的函数实例,name属性的值为anonymous
(new Function).name //'anonymous'
bind返回的函数,name属性值会加上bound前缀
function foo () {
}
foo.bind({
}).name // 'bound foo'
(function(){
}).bind({
}).name // 'bound'
5.箭头函数
基本用法
ES6允许使用“箭头”(=>)定义函数
var fn = val => val
//等同于
var fn = function(val){
return val
}
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
var fn = () => 5
//等同于
var fn = function() {
return 5
}
var sum = (num1, num2) => num1 + num2
//等同于
var sum = function(num1,num2){
return num1 + num2
}
如果箭头函数的代码块部分多于一条语句,就需要使用大括号将他们括起来
var fn = (a,b) {
if(a>b){
return a
}else{
return b
}
}
由于大括号被解释成代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上小括号没否则会报错
//报错
let getTem = id => {
id: id,
name:'Temp'
}
//不报错
let getTem = id => ({
id: id,
name: 'Temp'
})
使用注意点
箭头函数由几个使用注意点:
(1)函数体内的this对象,就是箭头函数定义时所在的对象,而不是使用时所在的对象
(2)不可以当做构造函数,也就是说,不能使用new命令,否则会报错
(3)不可以使用arguments对象,箭头函数内部的arguments对象不保存实参,可以使用rest参数来代替
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数
6.尾调用优化
什么是尾调用?
尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数
function fn(x){
return gn(x)
}
上面代码中,函数fn的最后一步是调用函数gn,这就叫尾调用
尾调用优化
注意只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则会就无法进行尾调用优化
function addone(a){
var one = 1
function inner(b){
return b + one
}
return inner(a)
}
版权声明
本文为[小沈曰]所创,转载请带上原文链接,感谢
https://szlsay.blog.csdn.net/article/details/124162657
边栏推荐
- Authing 正式加入 W3C 组织,将参与相关国际标准制定
- Free your hands and recommend a low code tool open source by Alibaba, yyds~
- MySQL多表查询小练习
- The third floor of leetcode Langya list - the container with the most water
- Oracle查询执行计划
- How to realize the automatic message sending function of wechat with vbs
- Finding a way to combine new technologies with itself is the key to the development of industrial Internet
- 数据库小练习
- How does PHP add an array element to an array
- 【Pinia】第二章 核心概念
猜你喜欢

Oracle合并数据操作(MERGE)

MySQL多表查询小练习

Leetcode0785. 判断二分图(medium,二分图,DFS)

软件测试流程与测试模型

Ffmpeg serial 2 - separate video and audio

微信小程序怎么实现商品列表跳转商品详情页功能

Detailed explanation of redis configuration file

MySQL is the most complete arrangement (interview questions + Notes + Guide Map), and the big interview companies are no longer stumped by mysql

软件的生命周期

LeetCode琅琊榜第三层-盛最多水的容器
随机推荐
One plus two earphone products: charge for 10 minutes and listen to music for 20 hours
How to realize the automatic message sending function of wechat with vbs
Finding a way to combine new technologies with itself is the key to the development of industrial Internet
一加连发两款耳机产品:充电10分钟 听歌20小时
省选游记暨后期基础规划
软件测试分类与软件测试的原则
POI Point of interesting.
【Pinia】第二章 核心概念
ServiceWorker 缓存与 HTTP 缓存
[charming Java] - data types and variables
【史上最全 BAT 必问高并发总结】
[test case level definition]
Lenovo announced the new progress of ESG: it promised that 100% of all computer products would contain recycled plastics by 2025
ROS机器人从起点到终点(四)蓝桥云实践复现
【WebGIS】WebGIS、桌面GIS、移动GIS、三维GIS的简介
华云积极响应合肥高新区抗疫号召:践行社会责任 贡献科技企业力量
Architecture document of outsourcing student management system
Nacos注册中心-服务注册与分级存储
JS to realize automatic scrolling of announcements
Push to origin / Master was rejected: error reporting solution