JavaScript函数之参数解析

作者:一介书生@毛豆前端

在JavaScript世界中函数是一等公民,它不仅拥有一切传统函数的使用方式(声明和调用),而且可以做到像简单值一样赋值、传参、返回,这样的函数也称之为第一级函数(First-class Function)。不仅如此,JavaScript中的函数还充当了类的构造函数的作用,同时又是一个Function类的实例(instance)。这样的多重身份让JavaScript的函数变得非常重要。本次讲一下有关函数参数的细节知识。

函数形参的默认值

es5中模拟默认参数:

function makeRequest(url, time, callback) {
    time = (typeof time !== 'undefined') ? time : 2000;
    callback = (typeof callback !== "undefined") ? callback : function () {
        //
    }
}
复制代码

在这个函数中timeout,callback为可选参数,如果不传系统会给他们赋予默认值。这种写法虽然很严谨,但是需要额外的代码。
es6中模拟默认参数:

function makeRequest(url, time=2000, callback=function () {}) {
  //
}
复制代码

在es6的标准中,只有url是必传参数,其余参数都是可选参数。如下调用都可以生效。

makeRequest('/foo)
makeRequest('/foo, 500)
makeRequest('/foo, 500, function() {//...})
复制代码

默认参数对arguments对象的影响

function mixArgs(first, second) {
    console.log(first === arguments[0])
    console.log(second === arguments[1])
    first = 'c'
    second = 'd'
    console.log(first === arguments[0])
    console.log(second === arguments[1])
}
复制代码

结果:

true  
true  
true  
true
复制代码

在非严格模式下,命名参数的变化会同步到arguments对象中,当first,second被赋予新值时arguments[0],arguments[1]也跟着更新了。但是在严格模式下,情况变得不一样。

function mixArgs(first, second) {
    'use strict'
    console.log(first === arguments[0])
    console.log(second === arguments[1])
    first = 'c'
    second = 'd'
    console.log(first === arguments[0])
    console.log(second === arguments[1])
}
mixArgs('a', 'b')
复制代码

结果如下:

true  
true  
false  
false
复制代码

严格模式下,无论参数如何变化,arguments对象是不变的。
在es6中,如果一个函数使用了默认参数值,则无论是否显式定义了严格模式,arguments对象的行为都将于es5的严格模式保持一致。

function mixArgs(first, second='b') {
    console.log(arguments.length)
    console.log(first === arguments[0])
    console.log(second === arguments[1])
    first = 'c'
    second = 'd'
    console.log(first === arguments[0])
    console.log(second === arguments[1])
}
mixArgs('a')
复制代码

结果如下:

1  
true  
false
false
false
复制代码

默认参数的临时死区

es6的let和const是存在临时死区TDZ,默认参数也存在同样的临时死区,在这里参数不可访问。与let声明类似,定义参数时会为每个参数创建一个新的标识符绑定,更改绑定在初始化时不可被访问。

function add(first = second, second) {
	return first + second
}
add(1, 1)
add(undefined, 1)
复制代码

add(1, 1)相当于执行以下代码:

let first = 1
let second = 1
复制代码

add(undefined, 1)相当于执行以下代码:

let first = second
let second = 1
复制代码

在初始化first时,second尚未初始化,所以导致程序报错。

不定参数

在函数的命名参数前加“…”就表明这是个不定参数,该参数作为一个数组,包含字它之后传入的所有参数。

function pick(obj, ...keys) {
	let result = {}
	for (let i = 0; i < keys.length; i++) {
		result[keys[i]] = obj[keys[i]]
	}
	return result
}
复制代码

这个函数模仿了Undescore.js的pick()方法,返回一个给定对象的副本。示例中只定义了一个参数是被复制的原始对象,其他参数为被复制属性的名称。

var article = {
	title: 'js-函数',
	author: 'zh',
	age: '20',
}
console.log(pick(article, 'title', 'age'))
复制代码

结果:

{title: "js-函数", age: "20"}
复制代码

此时函数的length属性统计的是函数的命名参数的数量,不定参数加入不会影响length属性的值。示例中pick的length为1,因为它值计算obj。

不定参数的使用有两条限制:

    1. 首先每个函数最多只能声明一个不定参数,不定参数的位置一定要放在所有参数的末尾。
    1. 不定参数不能用于对象字面量setter之中。如下写法是报错的。
let object = {
	set a(...val) {
		//
    }
}
复制代码

下节我们会讨论函数的箭头函数,下次再见。

转载于:https://juejin.im/post/5d070dfff265da1b8e709f63

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值