JavaScript函數之參數解析

做者:一介書生@毛豆前端javascript

在JavaScript世界中函數是一等公民,它不只擁有一切傳統函數的使用方式(聲明和調用),並且能夠作到像簡單值同樣賦值、傳參、返回,這樣的函數也稱之爲第一級函數(First-class Function)。不只如此,JavaScript中的函數還充當了類的構造函數的做用,同時又是一個Function類的實例(instance)。這樣的多重身份讓JavaScript的函數變得很是重要。本次講一下有關函數參數的細節知識。前端

函數形參的默認值

es5中模擬默認參數:java

function makeRequest(url, time, callback) {
    time = (typeof time !== 'undefined') ? time : 2000;
    callback = (typeof callback !== "undefined") ? callback : function () {
        //
    }
}
複製代碼

在這個函數中timeout,callback爲可選參數,若是不傳系統會給他們賦予默認值。這種寫法雖然很嚴謹,可是須要額外的代碼。
es6中模擬默認參數:git

function makeRequest(url, time=2000, callback=function () {}) {
  //
}
複製代碼

在es6的標準中,只有url是必傳參數,其他參數都是可選參數。以下調用均可以生效。es6

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])
}
複製代碼

結果:github

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的嚴格模式保持一致。ui

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')
複製代碼

結果以下:url

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) {
		//
    }
}
複製代碼

下節咱們會討論函數的箭頭函數,下次再見。

相關文章
相關標籤/搜索