在ES6以前是不能爲函數的參數指定默認值的,要想實現默認值只能經過判斷賦值的方式來實現,在ES6中容許函數爲參數設置默認值,主要是爲了提升代碼的可閱讀性,有利於代碼的優化。另外注意的是在參數賦值的時候,該參數不能重複使用,不能使用let const 進行定義。
// ES6 以前實現 function log(x, y) { y = y || 'World'; if (typeof y === 'undefined') { y = 'World'; } console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello World // ES6 中實現 function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello function Point(x = 0, y = 0) { this.x = x; this.y = y; } const p = new Point(); p // { x: 0, y: 0 } function foo(x = 5,x) { let x = 1; // 報錯,不能同名參數,不能對參數進行let const 定義 const x = 2; }
若是函數在調用的時候沒有提供參數,內部變量就不會產生,就會產生錯誤,經過提供函數的默認值能夠解決這種問題,以下:
function foo({x, y = 5}) { console.log(x, y); } foo() // 報錯 foo({x:1}) // 1 5 foo({x:2,y:3) // 2 3 foo({}) // undefined 5 function foo ({x,y = 5} = {}){ console.log(x,y) } foo() // undefined 5 這樣就是若是沒有在調用的時候傳值 就默認賦空對象。
以下例子:
function post(url, {b = '',type='get',h={}}){ console.log(type) } post('w.b.c',{}) // get post('w.b.c') // 報錯 // 改爲這樣就能夠了 function post(url, {b = '',type='get',h={}} = {}){ console.log(type) } post('w.b.c',{}) // get post('w.b.c') // get
下面例子的區別
// 寫法一 function m1({x = 0, y = 0} = {}) { return [x, y]; } // 寫法二 function m2({x, y} = { x: 0, y: 0 }) { return [x, y]; } 兩個都是有默認值在調用的時候都傳值或者都不傳值的時候狀況是同樣的。 可是若是傳空值,或者不傳值的狀況會有差別以下: m1({}) // 由於自己有默認值 因此爲 [0,0] m2({}) // 默認值爲空 解構賦值沒有傳值 因此 [undefined,undefined] // 其餘狀況同上 m1({x: 3}) // [3, 0] m2({x: 3}) // [3, undefined] m1({z: 3}) // [0, 0] m2({z: 3}) // [undefined, undefined]
若是定義了默認值的參數,應該是函數的尾參數。並且這個參數是沒法省略的,除非輸入undefined
函數參數指定了默認值以後,函數的length屬性將會減去指定了默認值的參數個數。由於該屬性認爲,指定了默認值的參數將不包含在預期參數個數中。以下:
(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
若是函數中的參數設置了默認值,那麼函數在聲明初始化的時候,參數會造成一個單獨的做用域,初始化完成後這個做用域就會消失,這種狀況只在參數設置了默認值的狀況下。以下:
var x = 1; function f(x, y = x) { console.log(y); } f(2) // 2 // 由於 設置了默認值 因此在調用 f 的時候就造成了做用域,這時候由於將x賦值給y 傳入的x 爲 2 因此y是2,若是這時候 調用的時候不傳值, 那麼x將指向全局,因此y = 1
利用參數默認值,能夠指定某一個參數不得省略,若是省略就報錯,以下
function throwIfMissing() { throw new Error('Missing parameter'); } function foo(mustBeProvided = throwIfMissing()) { return mustBeProvided; } foo() // Error: Missing parameter foo(2) // 2
ES6 中 增長了 rest 參數(...變量名),用於獲取函數多餘的參數,rest參數搭配的變量是一個數組,該變量將多餘的參數放入數組中。
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } add(2, 5, 3) // 10 // 注意:rest 參數以後不能再有其餘參數,另外rest參數也不計算在 函數的length屬性中。
ES6 中,若是函數參數使用了默認值,解構賦值,或者擴展運算符,那麼函數內部將不能顯式設定爲嚴格模式,不然會報錯。由於函數執行的時候 先執行函數參數,在執行函數體,可是由於只有在函數體中才能知道參數是否以嚴格模式執行,可是參數卻應該先於函數執行。有兩種方法能夠規避:1、 設置全局嚴格模式,2、把函數包在一個無參數的當即執行函數裏面。
返回函數的函數名,以下:
function foo(){} foo.name // foo var f = function(){} // ES5 f.name // '' // ES6 f.name // f var f = function c(){} f.name // c
ES6 容許使用 「箭頭」 (=>)定義函數
var f = v => v; // 等同於 var f = function (v) { return v; }; var f = () => 5; // 等同於 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同於 var sum = function(num1, num2) { return num1 + num2; }; // 若是箭頭函數後面的語句較多就要用大括號包裹起來 並return返回 var sum = (num1, num2) => { return num1 + num2; //rest 參數與箭頭函數結合的例子。 const numbers = (...nums) => nums; numbers(1, 2, 3, 4, 5) // [1,2,3,4,5] const headAndTail = (head, ...tail) => [head, tail]; headAndTail(1, 2, 3, 4, 5) // [1,[2,3,4,5]]
1. 函數體內的this對象,就是在定義時所在的對象,而不是使用時所在的對象。 2. 不能夠看成構造函數,也就是說,不可使用new命令,不然會拋出一個錯誤。 3. 不可使用arguments對象,該對象在函數體內不存在。若是要用,能夠用 rest 參數代替。 4. 不可使用yield命令,所以箭頭函數不能用做 Generator 函數。 5. 因爲箭頭函數沒有本身的this,因此固然也就不能用call()、apply()、bind()這些方法去改變this的指向。
1. 定義對象的方法,且該方法內部包括this 2. 動態定義this 的場合,如點擊事件中this 的指向
箭頭函數內部能夠在嵌套使用箭頭函數。
函數式編程的一個重要概念,指某個函數的最後一步是調用另外一個函數
function f(x){ return g(x); } // 一下都不屬於 // 狀況一 function f(x){ let y = g(x); return y; } // 狀況二 function f(x){ return g(x) + 1; } // 狀況三 function f(x){ g(x); }
只保留內層函數的調用幀。若是全部函數都是尾調用,那麼徹底能夠作到每次執行時,調用幀只有一項,這將大大節省內存。這就是「尾調用優化」的意義。
function f() { let m = 1; let n = 2; return g(m + n); } f(); // 等同於 function f() { return g(3); } f(); // 等同於 g(3);
注意,只有再也不用到外層函數的內部變量,內層函數的調用幀纔會取代外層函數的調用幀,不然就沒法進行「尾調用優化」。前端
函數調用自身,稱爲遞歸。若是尾調用自身,就稱爲尾遞歸。
在正常模式下,可使用減小調用棧,採用循環換掉遞歸的方法
ES6入門系列編程
ES6入門之let、contsegmentfault
ES6入門之字符串的擴展app
ES6入門之正則的擴展ide
ES6入門之數值的擴展函數式編程
Git教程函數
前端Git基礎教程post