函數(shù)擴(kuò)展
函數(shù)參數(shù)的默認(rèn)值
基本用法
function log(x,y){
y = y || 'cc';
console.log(x,y)
}
log('aa',false); // 'aa' 'cc'
log('aa',''); // 'aa' 'cc'
log('aa','bb'); // 'aa' 'bb'
當(dāng)
y的值為false或者‘’時(shí),其實(shí)還是應(yīng)該輸出fasle和’',正確的判斷方式應(yīng)該如下
function log(x,y){
// 判斷y的值是否被定義,
if(typeof y == 'undefined'){
y = 'cc'
}
console.log(x,y)
}
log('aa'); // 'aa' 'cc'
log('aa',false); // 'aa' false
log('aa',''); // 'aa' ''
log('aa','bb'); // 'aa' 'bb'
更為簡(jiǎn)單的
es6寫法
function log(x,y = 'cc'){
console.log(x,y)
}
log('aa'); // 'aa' 'cc'
log('aa',false); // 'aa' false
log('aa',''); // 'aa' ''
log('aa','bb'); // 'aa' 'bb'
function Point(x=0,y=0){
this.x = x;
this.y = y;
}
注意點(diǎn):
-
變量是默認(rèn)聲明的,不可以用
let或者const再次聲明function aaaa(x = 5){ let x = 1; const x = 1; } // Identifier 'x' has already been declared x變量已經(jīng)被聲明過(guò)了 -
使用參數(shù)默認(rèn)值時(shí),不允許有同名的參數(shù),否則報(bào)錯(cuò)。如果不使用參數(shù)默認(rèn)值,不會(huì)報(bào)錯(cuò),但我不會(huì)這么做
function bbbb(x,x,y=5){ } // Duplicate parameter name not allowed in this context 相同的參數(shù)名字不允許出現(xiàn) -
參數(shù)默認(rèn)值是惰性的,也就是說(shuō)參數(shù)的默認(rèn)值每次都會(huì)重新計(jì)算,如下
a的默認(rèn)值依賴于xlet x = 99; function cccc(a = x + 1){ console.log(a); } cccc(); // 100 x = 100; cccc(); // 101
與解構(gòu)賦值默認(rèn)值結(jié)合使用
function dddd({x,y=5}){
console.log(x,y);
}
dddd({}); // undefined 5
dddd({x:1}); // 1 5
dddd({x:1,y:2}); // 1 2
dddd({y:3}); // undefined 3
dddd({z:3}); // undefined 5
dddd(); // Cannot destructure property 'x' of 'undefined'
以下寫法會(huì)報(bào)錯(cuò),因?yàn)榈诙€(gè)參數(shù)并未設(shè)置默認(rèn)值,所以調(diào)用傳參必須有兩個(gè)參數(shù),缺少一個(gè)就會(huì)報(bào)錯(cuò)。
function fetch(url,{body='',method="GET",headers={}}){
console.log(method)
}
fetch('www.baidu.com',{}) // get
fetch('www.baidu.com') // 報(bào)錯(cuò)
為第二個(gè)參數(shù)設(shè)置了默認(rèn)值就不會(huì)報(bào)錯(cuò),且設(shè)置默認(rèn)值
function fetch(url,{body='',method="GET",headers={}} = {}){
console.log(method)
}
fetch('www.baidu.com',{}) // GET
fetch('www.baidu.com') // GET
fetch('www.baidu.com',{method:'POST'}) // POST
默認(rèn)值的寫法
區(qū)別:寫法一中的函數(shù)參數(shù)的默認(rèn)值是空對(duì)象,但是設(shè)置了對(duì)象解構(gòu)賦值的默認(rèn)值
? 寫法二中的函數(shù)參數(shù)的默認(rèn)值是一個(gè)有具體屬性的對(duì)象,沒(méi)有設(shè)置對(duì)象解構(gòu)賦值的默認(rèn)值
// 寫法一
function eeee({x=0,y=0} = {}){
return [x,y]
}
// 寫法二
function ffff({x,y} = {x:0,y:0}){
return [x,y]
}
// 都沒(méi)有參數(shù)的情況
eeee(); // [0,0]
ffff(); // [0,0]
// x,y都有值
eeee({x:1,y:1}) // [1,1]
ffff({x:1,y:1}) // [1,1]
// x有值,y無(wú)值
eeee({x:3}) // [3,0]
ffff({x:3}) // [3,undefined]
// x,y都無(wú)值
eeee({}); // [0,0]
ffff({}); // [undefined,undefined]
// 參數(shù)鍵不一樣
eeee({z:3}); // [0,0]
ffff({z:3}); // [undefined,undefined]
參數(shù)默認(rèn)值的位置
如果尾部參數(shù)設(shè)置了默認(rèn)值,那么可以省略,如果不是尾部參數(shù)設(shè)置了默認(rèn)值,參數(shù)值省略就是undefined,也就是說(shuō)參數(shù)是一一對(duì)應(yīng)的。
// 第一個(gè)參數(shù)設(shè)置默認(rèn)值
function gggg(x=1,y){
console.log(x,y);
}
gggg(); // 1 undefined
gggg(2); // 2 undefined
gggg(,1); // 報(bào)錯(cuò)
gggg(undefined, 3); // 1 3
// 第二個(gè)參數(shù)設(shè)置默認(rèn)值
function hhhh(x,y=1){
console.log(x,y)
}
hhhh(); // undefined 1
hhhh(3); // 3 1
hhhh(undefined,3); // undefined 3
// 多個(gè)參數(shù)的情況
function iiii(x,y=5,z){
console.log(x,y,z)
}
iiii(); // undefined 5 undefined
iiii(1); // 1 5 undefined
iiii(1,2); // 1 2 undefined
iiii(1, ,3); // 報(bào)錯(cuò)
iiii(1,undefined ,3); // 1 5 3
設(shè)置默認(rèn)值,只有參數(shù)值為undefined才會(huì)采用默認(rèn)值,否則還是原參數(shù)值
function jjjj(x=5,y=6){
console.log(x,y)
}
jjjj(undefined,null); // 5 null
函數(shù)的length屬性
length屬性會(huì)返回沒(méi)有指定默認(rèn)值的參數(shù)個(gè)數(shù)。1、預(yù)期傳入函數(shù)的參數(shù)個(gè)數(shù)。
2、某個(gè)參數(shù)指定默認(rèn)值之后,指定默認(rèn)值的參數(shù)之后的所有參數(shù)不計(jì)入
length3、結(jié)構(gòu)解耦的方式傳參 不計(jì)入
length
( function a(x) { } ).length // 1
( function a(x = 1) { } ).length // 0
( function a(x, y, z = 1) { } ).length // 1
( function a(x = 1, y, z) { } ).length // 0
( function a(...args) { } ).length // 0
作用域
設(shè)置默認(rèn)參數(shù)時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域,初始化結(jié)束之后,作用域消失。
var x = 1;
function kkkk(x, y = x){
console.log(x, y)
}
kkkk(2); // 2 2
// 參數(shù) y 的默認(rèn)值為變量 x ,調(diào)用函數(shù)時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域,默認(rèn)值變量 x 指向第一個(gè)參數(shù) x ,不是全局變量 x 。
let a = 1;
function llll(b = a){
let a = 2;
console.log(b);
}
llll(); // 1
// 函數(shù)參數(shù) y = x 形成一個(gè)單獨(dú)的作用域,如果當(dāng)前 x 沒(méi)有定義,則會(huì)向上查找,找到全局變量 x 。函數(shù)體內(nèi)部的 x 不會(huì)影響到默認(rèn)值變量 x
較為復(fù)雜的例子
var x = 1;
function foo ( x, y=function(){x = 2}){
var x = 3;
y();
console.log(x);
}
foo() // 3
console.log(x); // 1
// 函數(shù)的參數(shù)第一個(gè)是 x ,第二個(gè)是 y ,默認(rèn)值是一個(gè)匿名函數(shù),兩個(gè)參數(shù)構(gòu)成一個(gè)作用域,且匿名函數(shù)內(nèi)部的 x 指向第一個(gè)參數(shù) x ,
// foo 函數(shù)內(nèi)部重新定義了 x ,函數(shù)內(nèi)部的 x 和參數(shù)的 x 不在一個(gè)作用域內(nèi),所以不是一個(gè)變量,輸出為 3 ,全局的 x 是不會(huì)被影響的。
// 如果把 var 去了
var x = 1;
function foo ( x, y=function(){x = 2}){
x = 3;
y();
console.log(x);
}
foo() // 2
console.log(x); // 1
// 此時(shí) foo 函數(shù)內(nèi)部的 x 就指向了第一個(gè)參數(shù) x 。
應(yīng)用
-
利用參數(shù)默認(rèn)值指定某個(gè)參數(shù)不得省略,否則拋出錯(cuò)誤
function throwError(){ throw new Error('參數(shù)必須') } function mmmm(paramsMusted = throwError()){ return paramsMusted } mmmm(); // Error:參數(shù)必須 -
參數(shù)默認(rèn)值設(shè)為undefined,表示參數(shù)可省略
function nnnn(x = undefined){ console.log(111) } nnnn(); // 111