重學ES6 函數的擴展(上)

函數參數的默認值

基本用法

在ES6以前,咱們是這樣來作的javascript

function log( x, y){
    y = y || 'world'
    console.log(x, y)
}

log('hello') //hello world
log('hello', 'china') // hello china
log('hello','') // hello world
複製代碼

以上寫法會有一個問題,就是當咱們傳進去一個y值,可是其對應的布爾值爲false,例如 log('hello',''),結果被修改成了默認值! 因此,爲了不這個問題,咱們替換以下語句java

if(typeof y === 'undefined'){
    y = 'world'
}
複製代碼

在ES6裏面就簡單多了,能夠直接在參數設置默認值es6

function log(x, y = 'world') {
    console.log(x ,y)
}
log('hello') //hello world
log('hello', 'china') //hello china
log('hello','') // hello
複製代碼

有一點須要注意 參數默認值不是傳值的,而是每次從新計算默認值表達式的值,參數默認值是「惰性求值的」ajax

let x = 99

function foo(p = x + 1){
    console.log(p)
}

foo() //100

x = 100

foo() //101

//參數 p 的默認值是 x+1 每次調用函數 foo 都會從新計算 x+1 ,而不是默認 p 等於 100
複製代碼

注意:參數變量是默認聲明的,在函數體中,不能再用 let const 進行聲明,也 不容許有同名參數。數組

結合解構

function foo({x, y = 5}){
    console.log(x, y)
}

foo({}) // undefined 5
foo({x:1}) // 1, 5
foo({x: 1, y: 3}) // 1, 3
foo() //報錯
複製代碼

只有函數的參數是一個對象時,變量x y 纔會經過解構賦值生成。若是函數調用時,參數不是對象,變量x y 就不會生成,會報錯。ide

在前面文章 重學ES6 解構咱們他提到過函數參數的默認值,jQuery ajax的解構函數

這裏再用一個新的API寫一遍post

function fetch(url,{body = '', metthod = 'GET', headers = {}}){
    console.log( method )
}

fetch('http://example.com', {}) // GET
fetch('http://example.com') // 報錯
複製代碼

這個寫法不能省略第二個參數~那就太很差了。。。因此,咱們要再結合函數的默認值,就能夠省略第二個參數了fetch

function fetch(url,{body = '', metthod = 'GET', headers = {}} = {}){
    console.log( method )
}

fetch('http://example.com', {}) // GET
fetch('http://example.com') // GET
複製代碼

注意:在函數傳參解構中,只要傳入實際參數,那麼就拿傳入的實際參數進行解構,若是沒有傳入實際參數,且參數寫了默認值,函數參數獲得值是 undefined 時,被賦予默認值。ui

// demo 1
function m1 ({x = 0,y = 0} = {}){
    return [x, y]
}

// demo 2
function m2 ({x, y} = {x: 0, y: 0}){
    return [x, y]
}

//x y 都無值
m1({}) //[0, 0]
m2({}) // 沒有寫默認值,對實參進行解構,[undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
複製代碼

默認參數位置

一般,定義了默認值的參數應該是函數的尾參數。這樣能夠看出到底省略了哪些參數。

function f(x, y, z = 1){
    return [x, y, z]
}

f() // [undefined, undefined, 1]
複製代碼

函數的 length

指定了默認值之後,函數的 length 屬性將返回沒有指定默認值的參數個數。指定了默認值後,length屬性將失真

(function (a) {}).length //1
(function (a = 5)).length // 0 (function (b ,c ,a = 5)).length // 2 複製代碼

length 屬性 含義是 「函數預期傳入的參 數個數」 ,某個參數指定默認值之後,函數傳入參數個數就不包含這個了,rest參數也不會計入length屬性

做用域

設置了參數的默認值後,函數進行初始化時,參數會造成一個單獨的做用域。等到初始化結束,這個做用域就會消失。這種語法行爲在不設置參數時是不會出現的。

var x= 1

function f(x, y = x){  //至關於 let x 
    console.log(y)
}

f(2)
複製代碼
// 若是此時全局 x 不存在,就報錯了
function f(y = x){  //至關於 let y = x 
    console.log(y)
}

f()  // x is nit defined
複製代碼
var x = 1

function f(x = x){  //至關於 let x = x 暫時性死區
    console.log(x)
}

f()  // x is nit defined
複製代碼

若是參數是一個函數

let foo = 'ourter'

function bar (func = () => foo){ //在這裏,函數裏面的foo沒有定義,因此foo指向外層的 foo
    let foo = 'inner'
    console.log(func())
}

bar()
複製代碼

又一個例子

此例子,x共有3個,全局做用域下 foo函數參數做用域 還有 foo函數內部做用域,共三個,互不相同

var x =1

function foo(x, y = function() { x = 2}){
    var x = 3
    y()
    console.log(x)
}

foo() // 3
x // 1
複製代碼

可是,若是去掉 foo 函數 內部的 var x = 3 的 var,那麼就剩下兩個不一樣的x,即:全局下的x 和 函數 foo 參數做用域下的x ,由於函數內部的 x 和 函數參數的x 已是同一個x

var x =1

function foo(x, y = function() { x = 2}){
    x = 3
    y()
    console.log(x)
}

foo() // 2
x // 1
複製代碼

兩個例子都不會影響外部全局變量x的值。

應用

參數默認值,能夠指定某一個參數不能省略,若是省略了,就跑出一個錯誤

function throwIfMissing(){
    throw new Error('Missing parameter')
}

function foo(mustBeProvided = throwIfMissing()){
    return mustBeProvided
}

foo()
複製代碼

rest 參數

es6 引入了 rest參數,(形式爲 ...變量名),用於獲取函數的多餘參數,也就不須要使用 arguments 參數對象了。 rest參數搭配的變量是一個數組,該變量將多餘的參數放入其中。

function add(...values){
    let sum = 0
    for(var val of values){
        sum += val
    }
    return sum
}
add(1,2,3) // 6
複製代碼

幾個例子

以前,用arguments的寫法

// Array.prototype.slice.call(arguments) 將參數轉化爲數組
// array.sort
function sortNumbers() {
    return Array.prototype.slice.call(arguments).sort()
}

// rest 參數的寫法
//...numbers 將numbers 轉化爲數組
const sortNumbers = (...numbers) => numbers.sort()
複製代碼

rest參數改寫 push

function push(array,...items){
    items.forEach(function(item){
        array.push(item)
    })
}

var a = []

push(a,1,2,3)
複製代碼

rest 參數以後,不能再有其餘參數,因此,rest只能是最後一個參數。並且,函數的length,不包括rest參數。

相關文章
相關標籤/搜索