理解argument和 callee 屬性
阿新 • • 發佈:2019-01-25
arguments
javascript中的函式定義並未指定函式形參的型別,函式呼叫也未對傳入的實參值做任何型別檢查。實際上,javascript函式呼叫甚至不檢查傳入形參的個數
function add(x){
return x+1;
}
console.log(add(1));//2
console.log(add('1'));//'11'
console.log(add());//NaN
console.log(add(1,2));//2
同名形參
在非嚴格模式下,函式中可以出現同名形參,且只能訪問最後出現的該名稱的形參
function add(x,x,x){ return x; } console.log(add(1,2,3));//3 而在嚴格模式下,出現同名形參會丟擲語法錯誤 function add(x,x,x){ 'use strict'; return x; } console.log(add(1,2,3));//SyntaxError
引數個數
function add(x,y){
console.log(x,y);//1 undefined
}
add(1);
常常使用邏輯或運算子給省略的引數設定一個合理的預設值
function add(x,y){
y = y || 2;
console.log(x,y);//1 2
}
add(1);
[注意]實際上,使用y || 2是不嚴謹的,顯式地設定假值(undefined、null、false、0、-0、''、NaN)也會得到相同的結果。所以應該根據實際場景進行合理設定
當實參比形參個數要多時,剩下的實參沒有辦法直接獲得,需要使用即將提到的arguments物件
function add(x){ console.log(arguments[0],arguments[1],arguments[2])//1 2 3 return x+1; } add(1,2,3); arguments物件的length屬性顯示實參的個數,函式的length屬性顯示形參的個數 function add(x,y){ console.log(arguments.length)//3 return x+1; } add(1,2,3); console.log(add.length);//2 形參只是提供便利,但不是必需的 function add(){ return arguments[0] + arguments[1]; } console.log(add(1,2));//3
物件引數
function arraycopy(/*array*/from,/*index*/form_start,/*array*/to,/*index*/to_start,/*integer*/length){
//todo
}
通過名/值對的形式來傳入引數,這樣引數的順序就無關緊要了。定義函式的時候,傳入的實參都寫入一個單獨的物件之中,在呼叫的時候傳入一個物件,物件中的名/值對是真正需要的實引數據
function easycopy(args){
arraycopy(args.from,args.form_start || 0,args.to,args.to_start || 0, args.length);
}
var a = [1,2,3,4],b =[];
easycopy({form:a,to:b,length:4});
同步
function test(num1,num2){
console.log(num1,arguments[0]);//1 1
arguments[0] = 2;
console.log(num1,arguments[0]);//2 2
num1 = 10;
console.log(num1,arguments[0]);//10 10
}
test(1);
[注意]雖然命名引數和對應arguments物件的值相同,但並不是相同的名稱空間。它們的名稱空間是獨立的,但值是同步的
但在嚴格模式下,arguments物件的值和形參的值是獨立的
function test(num1,num2){
'use strict';
console.log(num1,arguments[0]);//1 1
arguments[0] = 2;
console.log(num1,arguments[0]);//1 2
num1 = 10;
console.log(num1,arguments[0]);//10 2
}
test(1);
當形參並沒有對應的實參時,arguments物件的值與形參的值並不對應
function test(num1,num2){
console.log(num1,arguments[0]);//undefined,undefined
num1 = 10;
arguments[0] = 5;
console.log(num1,arguments[0]);//10,5
}
test();
內部屬性
【callee】
arguments物件有一個名為callee的屬性,該屬性是一個指標,指向擁有這個arguments物件的函式
下面是經典的階乘函式(遞迴)
function factorial(num){
if(num <=1){
return 1;
}else{
return num* factorial(num-1);
}
}
console.log(factorial(5));//120
但是,上面這個函式的執行與函式名緊緊耦合在了一起,可以使用arguments.callee可以消除函式解耦function factorial(num){
if(num <=1){
return 1;
}else{
return num* arguments.callee(num-1);
}
}
console.log(factorial(5));//120
但在嚴格模式下,訪問這個屬性會丟擲TypeError錯誤
function factorial(num){
'use strict';
if(num <=1){
return 1;
}else{
return num* arguments.callee(num-1);
}
}
//TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
console.log(factorial(5));
這時,可以使用具名的函式表示式
var
factorial =
function
fn(num){
if
(num <=1){
return
1;
}
else
{
return
num*fn(num-1);
}
};
console.log(factorial(5));
//120