一、函數參數 1.可以使用預設參數 2.用let或const再次聲明參數會報錯,var不會。 3.使用參數預設值時,函數不能有同名參數。 4.參數預設值不是傳值的,而是每次都重新計算預設值表達式的值。也就是說,參數預設值是惰性求值的。 5.通常情況下,定義了預設值的參數,應該是函數的尾參數。 6.指 ...
一、函數參數
1.可以使用預設參數
function add(x=1,y=2){
return x+y;
}
2.用let或const再次聲明參數會報錯,var不會。
function add(x=1,y=2){
let x = 1; // error
const x = 2; // error
var x = 3;
}
3.使用參數預設值時,函數不能有同名參數。
// 不報錯
function foo(x, x, y) {
// ...
}
// 報錯
function foo(x, x, y = 1) {
// ...
}
4.參數預設值不是傳值的,而是每次都重新計算預設值表達式的值。也就是說,參數預設值是惰性求值的。
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
5.通常情況下,定義了預設值的參數,應該是函數的尾參數。
//No
function f(x = 1, y) {
return [x, y];
}
//Yes
function f(y, x = 1) {
return [x, y];
}
6.指定了預設值以後,函數的length屬性,將返回沒有指定預設值的參數個數。也就是說,指定了預設值後,length屬性將失真。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
如果設置了預設值的參數不是尾參數,那麼length屬性也不再計入後面的參數了。
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
7.一旦設置了參數的預設值,函數進行聲明初始化時,參數會形成一個單獨的作用域(context)。等到初始化結束,這個作用域就會消失。這種語法行為,在不設置參數預設值時,是不會出現的。
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
let x = 1;
function f(y = x) { //參數y = x形成一個單獨的作用域。這個作用域裡面,變數x本身沒有定義,
let x = 2; //所以指向外層的全局變數x。函數調用時,函數體內部的局部變數x影響不到預設值變數x。
console.log(y);
}
f() // 1
如果此時,全局變數x不存在,就會報錯。
function f(y = x) {
let x = 2;
console.log(y);
}
f() // ReferenceError: x is not defined
下麵這樣寫,也會報錯。
var x = 1;
function foo(x = x) {
// ...
}
foo() // ReferenceError: x is not defined
上面代碼中,參數x = x形成一個單獨作用域。實際執行的是let x = x,由於暫時性死區的原因,這行代碼會報錯”x 未定義“。
8.應用
利用參數預設值,可以指定某一個參數不得省略,如果省略就拋出一個錯誤。
function throwIfMissing() {
throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
return mustBeProvided;
}
foo()
// Error: Missing parameter
上面代碼的foo函數,如果調用的時候沒有參數,就會調用預設值throwIfMissing函數,從而拋出一個錯誤。
從上面代碼還可以看到,參數mustBeProvided的預設值等於throwIfMissing函數的運行結果(註意函數名throwIfMissing之後有一對圓括弧),這表明參數的預設值不是在定義時執行,而是在運行時執行。如果參數已經賦值,預設值中的函數就不會運行。
二、rest參數
轉自ECMAScript 6 入門