本系列屬於阮一峯老師所著的ECMAScript 6 入門學習筆記javascript
function Point(x =0,y=0){ this.x = x this.y = y } const p = new Point() p // {x:0,y:0} // 參數變量是默認聲明的,因此不能用let或const再次聲明 function(x = 5){ let x = 1 // error const x = 2 // error } // 使用參數默認值時,函數不能有同名參數 function foo(x,x,y=1){ // ... } // SyntaxError: Duplicate parameter name not allowed in this context // 參數默認不是傳值的,而是每次都從新計算默認值表達式的值。也就是說,參數默認值時惰性求值 let x = 99 function foo(p = x + 1){ console.log(p) } foo() // 100 x=100 foo() // 101
function(x,y=5){ console.log(x,y) } foo({}) // undefined 5 foo({x: 1}) // 1 5 foo({x: 1, y: 2}) // 1 2 foo() // TypeError: Cannot read property 'x' of undefined // 若是調用foo時沒提供參數,變量x和y就不會生成。經過提供函數參數的默認值,能夠避免 function foo({x,y=5}={}){ console.log(x,y) } foo() // undefined 5
// 一般狀況下,定義了默認值的參數,應該是函數的尾參數。若是非尾部設置默認值,實際上這個參數是無法省略的 // 例一 function(x=1,y){ return [x,y] } f() // [1, undefined] f(2) // [2, undefined]) f(, 1) // 報錯 f(undefined, 1) // [1, 1] //例二 function f(x,y=5,z){ return [x,y,z] } f() // [undefined, 5, undefined] f(1) // [1, 5, undefined] f(1, ,2) // 報錯 f(1, undefined, 2) // [1, 5, 2] // 上面代碼中,有默認值的參數都不是尾參數。這時,沒法只省略該參數,而不省略後面的參數,除非顯式輸入undefined,null沒有這個效果
指定了默認值以後,函數的length
屬性將返回沒有指定默認值的參數個數。java
(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
這是由於length
屬性的含義是,該函數預期傳入的參數個數。某個參數指定默認值之後,預期傳入的參數個數就不包括這個參數了。同理,rest 參數也不會計入length
屬性。es6
(function(...args) {}).length // 0
若是設置了默認值的參數不是尾參數,那麼length
屬性也再也不計入後面的參數了。數組
(function (a = 0, b, c) {}).length // 0 (function (a, b = 1, c) {}).length // 1
一旦設置參數的默認值,函數進行聲明初始化時,參數會造成一個單獨的做用域(context)。等到初始化結束,這個做用域就會消失。這種語法行爲,在不設置參數默認值時,是不會出現的。瀏覽器
let x = 1 function f(x,y=x){ console.log(y) } f(2) // 2 let x = 1 function f(y=x){ let x = 2 console.log(y) } f() // 1 // 若此時全局變量x不存在,就會報錯。若參數寫成x=x造成單獨做用域,會造成暫時性死區報錯
若是函數的默認值是一個函數,該函數的做用域也遵照這個規則函數
let foo = 'outer' function bar(func = () => foo){ let foo = 'inner' console.log(func()) } bar() // outer
ES6引入rest參數(形式爲...變量名
),用於獲取函數的多餘參數,這樣就不須要使用arguments
對象了。rest參數搭配的變量是一個數組,改變量將多餘的參數放入數組中。學習
function add(...values){ let sum = 0 for(let val of values){ sum += val } return sum } add(2,3,5) // 10 // 注意,rest參數以後不能再有其餘參數,不然會報錯 // 函數的length屬性,不包括rest參數
從ES5開始,函數內部尅設定爲嚴格模式。ES6作了一點修改,規定只要函數參數使用了默認值、解構賦值、或者拓展運算符,那麼函數內部就不能設定爲嚴格模式,不然會報錯。this
// 報錯 function doSomething(value = 070){ 'use strict' return value } // 兩種方法能夠規避這種限制 // 1、設定全局性的嚴格模式 'use strict' function doSomething(a,b=a){ // code } // 2、把函數包在一個無參數的當即執行函數裏面 const doSomething = (function(){ 'use strict' return function(value = 42){ return value } }())
函數的name
屬性,返回該函數的函數名。這是一個早就被瀏覽器支持,直到ES6才寫入標準的屬性rest
function foo(){} foo.name // 'foo' // 對於匿名函數,ES6的name屬性會返回實際的函數名,ES5則返回空字符串 var f = function(){} // ES5 f.name // '' // ES6 f.name // 'f' // 對於具名函數,ES5和ES6的name屬性都返回這個具名函數本來的名字 // Function構造函數返回的函數實例,name屬性的值爲anonymous (new Function).name // 'anonymous' // bind返回的函數,name屬性值會加上bound前綴 function foo(){} foo.bind({}).name // 'bound foo' (function(){}).bind({}).name // 'bound '
ES6容許使用」箭頭「(=>
)定義函數。code
var f = v => v //等同於 var f = function(v){ return v } // 無參數或多參數寫法 var f = () => 5 var sum = (num1,num2) => num1 + num2 // 返回對象 let getTempItem = id => ({id:id,name:'Temp'}) // 只有一行語句,且不須要返回值 let fn = () => void doesNotReturn() // 與變量解構結合使用 const full = ({first,last}) => first + '' + last // 與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 函數。