ES6 函式拓展內容

2021-10-08 12:28:57 字數 3747 閱讀 1417

es6允許為函式的引數設定預設值,即直接寫在引數定義的後面。

function

log(x,y=

'world'

)log

('hello'

)//hello world

log(

'hello'

,'yivi'

)//hello yivi

log(

'hello',''

)//hello

引數變數是預設宣告的,因此不能再用let或const再次宣告,也不能用同名的引數。

function

foo(x=5)

引數預設值可以與解構賦值的預設值結合使用。

function

foo(

)foo()

//undefined,5

foo(

)//error: cannot read property 'x' of undefined

foo(

)// 1,5

foo(

)//1,2

來看看下面兩種形式:

functionf1(

=)functionf2(

=)f1(

)//[0,0]f2(

)//[0,0]f1(

)//[3,undefined]f2(

)//[3,1]f1(

)//[undefined,undefined]f2(

)//[1,1]

如果定義了預設值的引數在函式的最尾部,則可以省略;如果非尾部的引數設定預設值,實際上這個引數無法省略,必須以undefined填充。

function

foo(x,y=

1,z)

foo();

//[undefined,1,undefined]

foo(1,

2,3)

//[1,2,3]

foo(1,

,2)//error

foo(

1,undefined,2)

//[1,1,2]

指定預設之後,函式的length方法將只返回沒有預設值的引數個數,也就是length將失真。這是因為length的本意是該函式預期傳入引數的個數。

(

function

(x,y,z=1)

).length =

2//引數個數為3,但返回2

一旦設定了預設值,函式宣告初始化的時候,引數就會形成乙個單獨的作用域,等到初始化結束,作用域就會失效。

var x=1;

function

foo(x,y=x)f(

2)//[2,2]

以上例子中,由於函式設定了預設值,在函式內部會形成單獨的作用域,因此函式中的y=x中的x指的是引數的x,而不是全域性變數x。

es6引入了rest引數...rest來獲取函式多餘的引數,這樣就無需引用arguments物件了。rest引數搭配的變數是乙個陣列,該變數將多餘的引數放入其中。

function

add(

...num)

return sum;

}add(1

,2,3

,4,5

)//15

注意:函式的length屬性並不包括rest 的引數個數

尾呼叫,顧名思義,就是指某個函式的最後一步是呼叫另乙個函式。

function

f(x)

//以下都不屬於尾呼叫

function

f(x)

function

f(x)

function

f(x)

尾呼叫的標誌是,必須是在最後呼叫函式,而不是操作呼叫後的結果。

我們知道,函式呼叫會在記憶體形成乙個「呼叫記錄」, 又稱「呼叫幀」(call frame),儲存呼叫位置和內部變數等資訊。如果在函式 a 的內部呼叫函式 b,那麼在 a 的呼叫幀上方還會形成一 個 b 的呼叫幀。等到 b 執行結束,將結果返回到 a, b 的呼叫幀才會消失。 如果函式 b 內部還呼叫函式 c,那就還有乙個 c 的呼叫幀,以此類推。所有的呼叫幀就形成乙個「呼叫棧」(call stack)。

尾呼叫由於是函式的最後一步操作,所以不需要保留外層函式的呼叫幀,因為呼叫位置、 內部變數等資訊都不會再用到了,直接用內層函式的呼叫幀取代外層函式的即可。

functionf(

)//等同於g(

3);

上面的**中,如果不是尾呼叫,函式f就需要儲存變數x,y的值、g的呼叫資訊等。但由於尾呼叫,函式f就結束了,所以記憶體中可以刪除f的呼叫記錄,只保留g的呼叫幀。這就是尾呼叫優化,可以大量節約記憶體。

遞迴是一種非常消耗記憶體的方法,因為其需要儲存大量的呼叫幀,容易發生記憶體溢位等錯誤,但尾遞迴就很好的解決了這個問題,因為他永遠只占用乙個呼叫幀。

// 階乘函式

function

factorial

(n)else

}// 我們尾遞迴真的太厲害了(老財富密碼了)

// 普通遞迴,不好用!尾遞迴,好用!

function

factorial

(n,total)

else

}//fibonacci數列

function

fibonacci

(n)else

}// 普通遞迴,不好用!尾遞迴,好用!

function

fibonacci

(n,ac =

1,ac =1)

else

}

上面的**似乎不是很合邏輯,為什麼我算乙個階乘還要傳乙個total進去呢,難道就不能直接給我結果嗎?答案是可以的。別忘了,es6給我們提供了預設值操作!

function

factorial

(n,total =1)

else

}factorial(5

)//120

還有一種尾呼叫的方法,就是在尾遞迴函式外再提供乙個正常形式的函式來進行尾遞迴:

function

tailfactorial

(n,total)

else

}function

factorial

(n)factorial(5

);//120

這其實是一種柯里化思維。等會兒!啥叫柯里化???

柯里化函式程式設計中有乙個重要的概念,叫做柯里化,意思是將多引數的函式轉化成單引數的形式。

function

curry

(fn,n)

//返回乙個可執行函式

}function

tailfactorial

(n,total)

else

}const factorial =

curry

(tailfactorial,1)

;factorial(5

)//120

es6的函式拓展

參考 1.增加函式預設值 es6允許為函式提供預設值,與解構賦值一起使用,非常地方便 function foo foo 相當於執行let 輸出undefined 5 foo 相當於執行let 輸出 1 5 foo 1 2 foo typeerror cannot read property x of...

ES6 函式的拓展 四

一 引數帶預設值函式 1 在函式形參可以賦予函式預設值 即實參嚴格匹配undefined時,在函式內部使用形參時呼叫它的預設值 2 函式name屬性 返回函式名稱,無名的函式返回空字串 3 函式length屬性 從左往右開始計算函式形參直到碰到帶有預設值形參時結束計算,這樣計算的形參個數 eg 普通...

es6 陣列拓展

陣列 屬性 constructor,length,prototype 方法 push,pop,shift,unshift 新增 splice,slice,reverse,sort,concat,filter,map,some,every 1 filter 過濾出符合條件的值,返回新陣列 var sp...