ES6函數(shù)擴(kuò)展

函數(shù)參數(shù)默認(rèn)值得添加

function log(x, y = 'World') {
  console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

下面兩種寫法有什么差別?

function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

// 寫法二
function m2({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

上面兩種寫法都對函數(shù)的參數(shù)設(shè)定了默認(rèn)值,區(qū)別是寫法一函數(shù)參數(shù)的默認(rèn)值是空對象,但是設(shè)置了對象解構(gòu)賦值的默認(rèn)值;寫法二函數(shù)參數(shù)的默認(rèn)值是一個(gè)有具體屬性的對象,但是沒有設(shè)置對象解構(gòu)賦值的默認(rèn)值。

// 函數(shù)沒有參數(shù)的情況
m1() // [0, 0]
m2() // [0, 0]

// x 和 y 都有值的情況
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x 有值,y 無值的情況
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]

// x 和 y 都無值的情況
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]

參數(shù)默認(rèn)值的位置

參數(shù)默認(rèn)值的位置
通常情況下,定義了默認(rèn)值的參數(shù),應(yīng)該是函數(shù)的尾參數(shù)。因?yàn)檫@樣比較容易看出來,到底省略了哪些參數(shù)。如果非尾部的參數(shù)設(shè)置默認(rèn)值,實(shí)際上這個(gè)參數(shù)是沒法省略的。

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

f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 報(bào)錯(cuò)
f(1, undefined, 2) // [1, 5, 2]

作用域

一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會形成一個(gè)單獨(dú)的作用域(context)。等到初始化結(jié)束,這個(gè)作用域就會消失。這種語法行為,在不設(shè)置參數(shù)默認(rèn)值時(shí),是不會出現(xiàn)的。如果參數(shù)的默認(rèn)值是一個(gè)函數(shù),該函數(shù)的作用域也遵守這個(gè)規(guī)則。請看下面的例子。

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

foo() // 3
x // 1

上面代碼中,函數(shù)foo的參數(shù)形成一個(gè)單獨(dú)作用域。這個(gè)作用域里面,首先聲明了變量x,然后聲明了變量y,y的默認(rèn)值是一個(gè)匿名函數(shù)。這個(gè)匿名函數(shù)內(nèi)部的變量x,指向同一個(gè)作用域的第一個(gè)參數(shù)x。函數(shù)foo內(nèi)部又聲明了一個(gè)內(nèi)部變量x,該變量與第一個(gè)參數(shù)x由于不是同一個(gè)作用域,所以不是同一個(gè)變量,因此執(zhí)行y后,內(nèi)部變量x和外部全局變量x的值都沒變。
利用參數(shù)默認(rèn)值,可以指定某一個(gè)參數(shù)不得省略,如果省略就拋出一個(gè)錯(cuò)誤。

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

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

foo()
// Error: Missing parameter

從上面代碼還可以看到,參數(shù)mustBeProvided的默認(rèn)值等于throwIfMissing函數(shù)的運(yùn)行結(jié)果(注意函數(shù)名throwIfMissing之后有一對圓括號),這表明參數(shù)的默認(rèn)值不是在定義時(shí)執(zhí)行,而是在運(yùn)行時(shí)執(zhí)行。如果參數(shù)已經(jīng)賦值,默認(rèn)值中的函數(shù)就不會運(yùn)行。

另外,可以將參數(shù)默認(rèn)值設(shè)為undefined,表明這個(gè)參數(shù)是可以省略的。
function foo(optional = undefined) { ··· }

箭頭函數(shù)

箭頭函數(shù)有幾個(gè)使用注意點(diǎn)。

  1. 函數(shù)體內(nèi)的this對象,就是定義時(shí)所在的對象,而不是使用時(shí)所在的對象。
  2. 不可以當(dāng)作構(gòu)造函數(shù),也就是說,不可以使用new命令,否則會拋出一個(gè)錯(cuò)誤。
  3. 不可以使用arguments對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以用 rest 參數(shù)代替。
  4. 不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)。
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

上面代碼中,setTimeout的參數(shù)是一個(gè)箭頭函數(shù),這個(gè)箭頭函數(shù)的定義生效是在foo函數(shù)生成時(shí),而它的真正執(zhí)行要等到 100 毫秒后。如果是普通函數(shù),執(zhí)行時(shí)this應(yīng)該指向全局對象window,這時(shí)應(yīng)該輸出21。但是,箭頭函數(shù)導(dǎo)致this總是指向函數(shù)定義生效時(shí)所在的對象(本例是{id: 42}),所以輸出的是42。

請問下面的代碼之中有幾個(gè)this?

function foo() {
  return () => {
    return () => {
      return () => {
        console.log('id:', this.id);
      };
    };
  };
}

var f = foo.call({id: 1});

var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1

上面代碼之中,只有一個(gè)this,就是函數(shù)foo的this,所以t1、t2、t3都輸出同樣的結(jié)果。因?yàn)樗械膬?nèi)層函數(shù)都是箭頭函數(shù),都沒有自己的this,它們的this其實(shí)都是最外層foo函數(shù)的this。

搬運(yùn)自:阮一峰ES6教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容