Es6 函數(shù)的擴(kuò)展

1.函數(shù)的默認(rèn)值

  • 以前給函數(shù)的參數(shù)設(shè)置默認(rèn)值
function fn(x,y){
    y=y||'world'
}
fn('Hello') // Hello World
fn('Hello', 'China') // Hello China
fn('Hello', '') // Hello World
  • Es6的寫法
function fn(x=0,y=10){
     return x+y
}
fn() // 0
fn(10) // 20
fn(10,20) // 30
  • 不可以使用let或者const重新聲明參數(shù)
function fn(x){
    let x=10;
}
//error

上面代碼中俘侠,參數(shù)變量x是默認(rèn)聲明的囚灼,在函數(shù)體中坷澡,不能用let或const再次聲明,否則會報錯差牛。

  • 使用函數(shù)參數(shù)默認(rèn)值不可以有相同的參數(shù)
function fn(x,x,y){
}

上邊的代碼不會報錯,因為并沒有設(shè)置默認(rèn)值,但是第二個的x的值會覆蓋第一個x

function fn(x=5,x,y=10){
//error
}

  • 函數(shù)參數(shù)默認(rèn)值與解構(gòu)賦值結(jié)合使用

    • 參數(shù)默認(rèn)值可以與解構(gòu)賦值的默認(rèn)值爬立,結(jié)合起來使用。
    function fn({a,y:5}){
        console.log(a,y)
    }
    fn() //error 
    fn({}) // undefined,5
    fn({x:1}) // 1,5
    fn({x:1,y:5}) // 1,6
    

    為啦防止上邊的第一種錯誤的情況,可以這么寫:

    function fn({x=1,y}={}){
        console.log(x,y)
    }
    fn() //x:1,y:undefined
    

    仔細(xì)比較這個代碼和上邊的代碼有什么不同,這里的fn執(zhí)行的時候沒有傳入?yún)?shù),而上邊的也沒有傳入?yún)?shù),為什么這里的能正常執(zhí)行呢,是應(yīng)為,上邊的代碼沒有在fn()執(zhí)行的時候添加和參數(shù)默認(rèn)值解構(gòu)的對象,而這里的是在參數(shù)里邊已經(jīng)做啦解構(gòu)賦值,只不過是一個空對象而已.

  • 函數(shù)的length

    • 函數(shù)的length屬性万哪,將返回沒有指定默認(rèn)值的參數(shù)個數(shù)侠驯。也就是說,指定了默認(rèn)值后奕巍,length屬性將失真
        function fn(x){
      
        }
      
        console.log(fn.length) // 1
      
        function fn1(x=1){
      
        }
        console.log(fn.length) //0
      
  • 作用域

    • 一旦參數(shù)設(shè)置啦默認(rèn)值,函數(shù)在聲明初始化時會形成一個單獨的域,等到初始化結(jié)束,域消失,參數(shù)沒有設(shè)置默認(rèn)值時,是不會形成這個域的
let x= 10;
function fn (x,y=x){ 
    console.log(y)
}
fn(1) // 1

上面代碼中吟策,參數(shù)y的默認(rèn)值等于變量x。調(diào)用函數(shù)f時的止,參數(shù)形成一個單獨的作用域檩坚。在這個作用域里面,默認(rèn)值變量x指向第一個參數(shù)x,而不是全局變量x匾委,所以輸出是2拖叙。

let x = 1;

function fn(y = x) {
  let x = 2;
  console.log(y);
}

fn() // 1

在上邊的代碼中,雖然函數(shù)里有變量x,但是這個作用域是在函數(shù)聲明初始化的時候形成的,所以里邊里邊的x指向全局的x.

function f(y = x) {
  let x = 2;
  console.log(y);
}

f() // ReferenceError: x is not defined

報錯是因為在全局中沒有找到全局變量x

var x = 1;

function foo(x = x) {
  // ...
}

foo() // ReferenceError: x is not defined

上面代碼中,參數(shù)x = x形成一個單獨作用域赂乐。實際執(zhí)行的是let x = x薯鳍,由于暫時性死區(qū)的原因,這行代碼會報錯”x 未定義“挨措。

2.rest參數(shù)

ES6 引入 rest 參數(shù)(形式為...變量名)挖滤,用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對象了浅役。rest 參數(shù)搭配的變量是一個數(shù)組斩松,該變量將多余的參數(shù)放入數(shù)組中。

function add(...values) {
  let sum = 0;

  for(var i = 0;i < values.length;i++){
    num+=values[i]
  }

  return sum;
}

add(2, 5, 3) // 10
  • rest必須是最后一個參數(shù),否則會報錯
function fn(x,...values,y){
}
//error
  • 函數(shù)的length屬性觉既,不包括 rest 參數(shù)惧盹。
function fn(x,y=2,...values){

}
console.log(fn.length)

3.嚴(yán)格模式

從 ES5 開始,函數(shù)內(nèi)部可以設(shè)定為嚴(yán)格模式 , ES2016 做了一點修改奋救,規(guī)定只要函數(shù)參數(shù)使用了默認(rèn)值岭参、解構(gòu)賦值、或者擴(kuò)展運算符尝艘,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式演侯,否則會報錯。

下邊是報錯的一些例子:

function a(a, b = a) {
  'use strict';
  // code
}

// 使用啦參數(shù)設(shè)置默認(rèn)值報錯
const a= function ({a, b}) {
  'use strict';
  // code
};

// 使用啦解構(gòu)賦值報錯
const a= (...a) => {
  'use strict';
  // code
};
// 報錯
function doSomething(value = 070) {
  'use strict';
  return value;
}

上面代碼中背亥,參數(shù)value的默認(rèn)值是八進(jìn)制數(shù)070秒际,但是嚴(yán)格模式下不能用前綴0表示八進(jìn)制,所以應(yīng)該報錯狡汉。但是實際上娄徊,JavaScript 引擎會先成功執(zhí)行value = 070,然后進(jìn)入函數(shù)體內(nèi)部盾戴,發(fā)現(xiàn)需要用嚴(yán)格模式執(zhí)行寄锐,這時才會報錯。

解決辦法
1.設(shè)置全局的嚴(yán)格模式

'use strict';

function a(a, b = a) {
  // code
}

2.套在一個無參數(shù)的自執(zhí)行函數(shù)里

let a =(function(){
      'use strict';
    retuen function (x=2,y){
        console.log(x,y)
    }
}())

4.name 屬性

  • 函數(shù)的name屬性尖啡,返回該函數(shù)的函數(shù)名橄仆。
function foo() {}
foo.name // "foo"
  • ES6 對這個屬性的行為做出了一些修改。如果將一個匿名函數(shù)賦值給一個變量衅斩,ES5 的name屬性盆顾,會返回空字符串,而 ES6 的name屬性會返回實際的函數(shù)名畏梆。
var f = function () {};

// ES5
f.name // ""

// ES6
f.name // "f"
  • 如果將一個具名函數(shù)賦值給一個變量您宪,則 ES5 和 ES6 的name屬性都返回這個具名函數(shù)原本的名字奈懒。
var a = function fn(){
 
};
//Es5
console.log(a.name) // fn
//Es6
console.log(a.name) // fn
  • Function構(gòu)造函數(shù)返回的函數(shù)實例,name屬性的值為anonymous宪巨。
(new Function).name // "anonymous"

5.Es6允許使用“箭頭”(=>)定義函數(shù)磷杏。

  • 基本用法
var f = v => 1;
f() //1
// v 函數(shù)的形參, 1 函數(shù)的實參和返回值
  • 如果有多個參數(shù),使用一個圓括號代表參數(shù)部分
var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

  • 如果要返回一個對象必須在對象外邊加圓括號
//報錯
let obj= id => { id: id, name: "Temp" };
//不報錯
let obj= id => ({ id: id, name: "Temp" });
  • 與解構(gòu)賦值的結(jié)合使用
 var f = ({name,age}) => name+' '+age
 f({name:'suo',age:28}) //"suo 20"

箭頭函數(shù)使用注意事項

(1)函數(shù)體內(nèi)的this對象,就是定義時所在的對象揖铜,而不是使用時所在的對象茴丰。
(2)不可以當(dāng)作構(gòu)造函數(shù),也就是說天吓,不可以使用new命令贿肩,否則會拋出一個錯誤。
(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ù)是一個箭頭函數(shù)茂嗓,這個箭頭函數(shù)的定義生效是在foo函數(shù)生成時,而它的真正執(zhí)行要等到 100 毫秒后科阎。如果是普通函數(shù)述吸,執(zhí)行時this應(yīng)該指向全局對象window,這時應(yīng)該輸出21锣笨。但是蝌矛,箭頭函數(shù)導(dǎo)致this總是指向函數(shù)定義生效時所在的對象(本例是{id: 42}),所以輸出的是42错英。

箭頭函數(shù)可以讓setTimeout里面的this入撒,綁定定義時所在的作用域,而不是指向運行時所在的作用域椭岩。下面是另一個例子茅逮。

6.雙冒號運算符

  • 函數(shù)綁定運算符是并排的兩個冒號(::),雙冒號左邊是一個對象判哥,右邊是一個函數(shù)氮唯。該運算符會自動將左邊的對象,作為上下文環(huán)境(即this對象)姨伟,綁定到右邊的函數(shù)上面。
foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

  • 如果雙冒號左邊為空豆励,右邊是一個對象的方法夺荒,則等于將該方法綁定在該對象上面瞒渠。
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;

let log = ::console.log;
// 等同于
var log = console.log.bind(console);

7尾調(diào)用

  • 什么是尾調(diào)用

    • 尾調(diào)用是函數(shù)式編程的一個重要概念,本身非常簡單技扼,一句話就能說清楚伍玖,就是指某個函數(shù)的最后一步是調(diào)用另一個函數(shù)。

    • 調(diào)用之后再操作的都不算尾調(diào)用

    • 尾調(diào)用不一定出現(xiàn)在函數(shù)尾部,只要是最后一步操作就好

     // 情況一
    function f(x){
      let y = g(x);
      return y;
    }
    
    // 情況二
    function f(x){
      return g(x) + 1;
    }
    
    // 情況三
    function f(x){
      g(x);
    }
    

情況一 : 調(diào)用之后有操作;
情況二 : 調(diào)用之后有操作;
情況三 : function(){g(x) return undefined;};

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末剿吻,一起剝皮案震驚了整個濱河市窍箍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丽旅,老刑警劉巖椰棘,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異榄笙,居然都是意外死亡邪狞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門茅撞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帆卓,“玉大人,你說我怎么就攤上這事米丘〗A睿” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵拄查,是天一觀的道長吁津。 經(jīng)常有香客問我,道長靶累,這世上最難降的妖魔是什么腺毫? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮挣柬,結(jié)果婚禮上潮酒,老公的妹妹穿的比我還像新娘。我一直安慰自己邪蛔,他們只是感情好急黎,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著侧到,像睡著了一般勃教。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匠抗,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天故源,我揣著相機(jī)與錄音,去河邊找鬼汞贸。 笑死绳军,一個胖子當(dāng)著我的面吹牛印机,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播门驾,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼射赛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奶是?” 一聲冷哼從身側(cè)響起楣责,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎聂沙,沒想到半個月后秆麸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡逐纬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年蛔屹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豁生。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡兔毒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出甸箱,到底是詐尸還是另有隱情育叁,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布芍殖,位于F島的核電站豪嗽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏豌骏。R本人自食惡果不足惜龟梦,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窃躲。 院中可真熱鬧计贰,春花似錦、人聲如沸蒂窒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洒琢。三九已至秧秉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衰抑,已是汗流浹背象迎。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留呛踊,地道東北人砾淌。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓完丽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拇舀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容