JS中函數定義時不需要指定參數的類型,函數調用時也不會對傳入的參數進行類型檢查,甚至參數的個數也不做檢查,了解這些特殊情況,避免開發出錯。
參數個數
當實參比形參的個數少時,多餘的形參會被設定成undefined。
function fn(a,b,c){
console.log(c) // undefined
}
fn(1,2)
當實參比形參的個數多時,多餘的實參在函數中無法直接擷取到,可以通過arguments對象擷取。
function fn(a,b) {
console.log(arguments[0],arguments[1],arguments[2]) // 1 2 3
}
fn(1,2,3)
JS函數中的參數在内部是用一個數組表示的,可以通過arguments對象通路這個參數數組,進而擷取到傳入給函數的每一個參數。
注意: arguments對象是一個類數組對象,不是Array對象的執行個體。可以使用方括号文法通路每一個元素。
arguments對象的length屬性顯示實參的個數,函數的length屬性顯示形參的個數。
function fn(a,b) {
console.log(arguments.length) // 3
console.log(fn.length) // 2
}
fn(1,2,3)
參數同步
在嚴格模式下,arguments對象的值和形參是獨立的。在非嚴格模式下,它們的值是同步的。
// 示例1
function fn(a) {
'use strict'
console.log(a, arguments[0]) // 1 1
a = 2
console.log(a, arguments[0]) // 2 1
arguments[0] = 3
console.log(a, arguments[0]) // 2 3
}
fn(1)
// 示例2
function fn(a) {
console.log(a, arguments[0]) // 1 1
a = 2
console.log(a, arguments[0]) // 2 2
arguments[0] = 3
console.log(a, arguments[0]) // 3 3
}
fn(1)
callee屬性
arguments對象的callee屬性是一個指針,指向擁有這個arguments對象的函數。
注意: 嚴格模式下禁止使用該屬性,會報錯
// 階層函數
function factorial(num) {
if(num <=1) {
return 1
} else {
return num * factorial(num - 1)
}
}
factorial(3) // 6
上面的函數有一個問題,就是函數的執行和函數名耦合在了一起,這時可以使用callee屬性解決這個問題。
function factorial(num) {
if(num <=1) {
return 1
} else {
return num * arguments.callee(num - 1)
}
}
factorial(3) // 6
由于callee屬性在嚴格模式下報錯,可以使用具名函數表達式。
var factorial = function fn(num){
if(num <=1){
return 1
}else {
return num * fn(num - 1)
}
}
factorial(3) // 6
caller屬性
arguments對象的caller屬性不是一個标準屬性,不贊成用于生産環境,但浏覽器都支援它。該屬性儲存了調用目前函數的函數的引用,如果在全局作用域中調用目前函數,它的值是null。
// 示例1
function outer() {
inner()
}
function inner() {
// inner是目前函數,outer是調用目前函數的函數
console.log(inner.caller) // outer() { inner() }
}
outer()
// 示例2
function inner() {
console.log(inner.caller)
}
inner() // null
函數重載
函數重載簡單了解就是同一個函數,可以根據不同的參數(比如類型不同或數量不同)執行不同的處理邏輯。
由于JS無法為同一個函數編寫不同的定義标簽,是以真正的重載是做不到的,隻能通過檢查傳入函數中參數的類型和數量作出不同的反應,來模仿方法的重載。
function doAdd(){
if(arguments.length == 1){
alert(arguments[0] + 10);
}else if(arguments.length == 2){
alert(arguments[0] + arguments[1]);
}
}
doAdd(10);//20
doAdd(30,20);//50
參數傳遞
function fn(num) {
num += 10
return num
}
var count = 10
var result = fn(count)
console.log(count) // 10 原始值不會改變
console.log(result) // 20
function fn(obj) {
obj.name = 'hello'
}
var person = new Object()
fn(person)
console.log(person.name) // 'hello'
function fn(obj) {
obj = new Object();
obj.name = 'hello';
}
var person = new Object()
fn(person)
console.log(person.name) // undefined
部落格: https://blog.86886.wang
GitHub: https://github.com/wmui