ES6初探-let const與箭頭函數(shù)

let const

let

1. let 聲明的變量不會有變量提升,且在 『一個花括號{}』 內(nèi)部聲明的變量潜沦,會形成塊級作用域

??

{
  console.log(a)
  // Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 111
  console.log(a)
  // 打印出 111
}
console.log(a)
// Uncaught ReferenceError: a is not defined

上例中,可以的值 let 并不存在變量提升绪氛。所有在 let a 之前使用 a 會報錯唆鸡,所以導(dǎo)致 第一個 console.log(a) 報錯, 且在花括號內(nèi)部 let 聲明的變量 會形成塊級作用域所以外部是無法取到 a 的值枣察,所有花括號外部的 console.log(a) 會直接報錯争占。

上面的如是在花括號內(nèi)部使用 var 聲明變量

{
  console.log(a)
  var a = 111
  console.log(a)
}
console.log(a)

等價于

var a 
console.log(a)
a = 111
console.log(a)
console.log(a)
// undefined
// 111
// 111

因為var 聲明會有變量提升,且花括號內(nèi)部并沒有形成一個塊級作用域序目。所以執(zhí)行的結(jié)果就會不符合直覺臂痕,造成困惑。

2. let 不能重復(fù)聲明變量

??

let a = 1
// var a = 1

let a = 2
// Uncaught SyntaxError: Identifier 'a' has already been declared

let 不能重復(fù)聲明一個變量猿涨,但是如果不同的變量是在不同的塊級作用域是可行的刻蟹。

??

{
  let a = 1
  {
    let a = 2
    {
      let a = 3
    }
  }
}

以上代碼a 隸屬于不同的塊級作用域所以并不存在重復(fù)聲明。

const

const的用法與 let 有還多相似之處嘿辟。但是 const 也有其獨特的地方

  1. const 聲明初始必須賦值,其已經(jīng)賦值的的變量片效。不能再次賦值
const a = 1
a = 2
// Uncaught TypeError: Assignment to constant variable
  1. const 賦值的的變量是對象字面量红伦,可以修改對象內(nèi)部屬性的值。
const obj = {
  name: 'xxx',
  age: '21'
}

obj['name'] = 'yyy'

obj = {anme: 'xxx', age: 21}
// b報錯
// Assignment to constant variable.
  1. const 適用于常量
const pi = 3.141
const e = 2.718

let 聲明與 for 循環(huán)以及循環(huán)內(nèi)的函數(shù)

?? 需求: 在控制臺間隔一秒打印出 1淀衣, 2昙读, 3, 4膨桥, 5

for (var i=1; i<=5; i++) {     
    setTimeout( function timer() {
        console.log(i) }, i*1000 );
}

結(jié)果如下圖間隔一秒打印出 6, 6, 6, 6, 6

for循環(huán)與函數(shù)

錯誤分析: 這是因為在循環(huán)迭代的過程中蛮浑,貫穿始終的都只有一個 i 在被共享。并沒有新的 i 的值產(chǎn)生只嚣,所以最后 循環(huán)結(jié)束 i 也有最后一次循環(huán)的一個值(最后一次循環(huán) i = 5, 但是 i++ 還會執(zhí)行所以最終i的值為6)沮稚。

解決問題:

  1. 在內(nèi)部添加一個 j 存儲 的值
for (var i = 1; i <= 5; i++) {
  var j = i
  setTimeout(function timer() {
    console.log(i)
  }, i*1000)
}

打印的結(jié)果是5,5册舞,5蕴掏,5,5, 如下圖所示:

for循環(huán)與函數(shù)-1

分析:
首先上面的代碼等價于:

// var 聲明變量提升
var i
var j
for (i = 1; i <= 5; i++) {
  j = i
  setTimeout(function timer() {
    console.log(i)
  }, i*1000)
}

首先在花括號內(nèi)部有一個 j 的值可以存儲 i, 但是 j 的并不是存在一個局部作用域而是全局作用域调鲸。在 i 的值迭代的過程中盛杰,j 的值也是跟著迭代。最終全局作用域下藐石,j 只有一個值(i 最后一次循環(huán)的值 i=5),而不是五個不同的值即供。

  1. 構(gòu)建一個立即執(zhí)行函數(shù)
for (var i = 1; i <= 5; i++) {
  (function() {
    var j = arguments[0]
    setTimeout(function timer() {
    console.log(j)
    }, i*1000)
  })(i)
}

一次打印出 1, 2于微, 3逗嫡, 4青自,5。最后圓括號的 i 的值變成 6祸穷。在上面的IIFE中性穿,每次 i 的值迭代就會存儲在 IIFE所在的局部作用域中的變量 j 中(IIFE局部作用域中一個存在5個 i 的值分別是 1, 2雷滚, 3需曾, 4, 5)祈远。

  1. let 聲明 圓括號 i 的值或是花括號內(nèi) j 的值

for (let i = 1; i <= 5; i++) {
   // i 的就在(),其實{}是訪問不到 i 的值的
  // let i(copy) = i JS自動添加的
    setTimeout(function timer() {
    console.log(i)
    }, i*1000)
  // 結(jié)束循環(huán) i(copy)把值賦值給圓括號內(nèi)部的 i 
}
// 間隔一秒 打印出 1呆万,2,3车份,4谋减,5

console.log(i)
// 報錯
// Uncaught ReferenceError: i is not defined

或是

for (var  i = 1; i <= 5; i++) {
  let j = i
    setTimeout(function timer() {
    console.log(j)
    }, i*1000)
}
// 間隔一秒 打印出 1,2扫沼,3出爹,4,5
console.log(i)
// 6

首先兩種方式都可以達成目的缎除,3-①每次迭代都存在 {} 內(nèi)部都會新建一個同名變量严就,并把迭代的值賦值給這個同名變量let i = i,所以循環(huán)結(jié)束也就是會在花括號內(nèi)部存在5個副本i, 分別是i1 i2 i3 i4 i5器罐。循環(huán)結(jié)束 副本 i 的值梢为,會賦值給i圓括號內(nèi)部的 i ,(let i = 1; i <= 5; i+=) i 的值值存在這個圓括號內(nèi)部轰坊。


箭頭函數(shù)

箭頭函數(shù)的語法

箭頭函數(shù)的基本用法:
??

var fn = function(a) {
  console.log(a)
}

// 等價于下面的箭頭函數(shù)
var fn1 = a => console.log(a)

語法:

  1. 去掉function關(guān)鍵字

  2. 添加一個 =>

  3. 多個參數(shù)加括號铸董,不同參數(shù)用逗號隔開。一個參數(shù)括號可選擇(加與不加括號都行)

  4. 沒有參數(shù)括號不能省肴沫。沒有執(zhí)行語句{}花括號不能省

  5. 只有一個語句花括號可以省略(且同時需要省略return 關(guān)鍵字),多個語句必須加花括號(return 關(guān)鍵字不能省略)

更多細節(jié)下面通過??來展示:

  • 當箭頭函數(shù)返回的值是一個對象字面量:
var fn = function() {
  return {name: 'xxx', age: 18}
}

var fn1 = () => {name: 'xxx', age: 18}
// Uncaught SyntaxError: Unexpected token ':'

上面函數(shù) fn 返回的是一個對象字面量粟害,按著下面的方式簡化成箭頭函數(shù) fn1 會發(fā)現(xiàn)報錯。所以如果是return 返回一個對象字面量應(yīng)該用 ()括號 包裹該對象字面量

var fn1 = () => ({name: 'xxx', age: 18})
fn1()
// {name: 'xxx', age: 18}
  • 當箭頭函數(shù)與IIFE(立即執(zhí)行函數(shù)):
    普通構(gòu)建的立即執(zhí)行函數(shù):
(function() {
  console.log('IIFE')
}.call())
// IIFE

(function() {
  console.log('IIFE')
}).call()
// IIFE

箭頭函數(shù)的立即執(zhí)行函數(shù)

(() => console.log('IIFE'))()
// IIFE

(() => console.log('IIFE')())
// () => console.log('IIFE')()

所以使用箭頭函數(shù)構(gòu)造IIFE,只能用(arrow Function)()這種方式樊零。

箭頭函數(shù)的運用

運用箭頭函數(shù)的就必須了解箭頭函數(shù)的特性我磁,以及傳統(tǒng)方式聲明的函數(shù)的一些弊端

  1. 箭頭函數(shù)可以簡化代碼。
  1. 箭頭函數(shù)本身沒有this綁定驻襟,而傳統(tǒng)方式聲明的函數(shù)this的值往往難以確定夺艰。

??箭頭函數(shù)與數(shù)組結(jié)合簡化代碼
var arr = [10, 0, 100, -3, 2, 99, 8]。現(xiàn)在的需求是按照從小到大沉衣,重排

var arr = [10, 0, 100, -3, 2, 99, 8]
// 直接使用arr.sort這個API
arr.sort(function(v1, v2) {
  return v1 - v2
})
// [-3, 0, 2, 8, 10, 99, 100]

上面的代碼如果使用箭頭函數(shù)會更加簡便

arr.sort((v1, v2) => v1 -v2)
// [-3, 0, 2, 8, 10, 99, 100]

所以在使用Array.sort Array.reduce Array.forEach Array.map郁副,對這些API的回調(diào)函數(shù)使用箭頭函數(shù),可以使代碼更加簡潔豌习。

??箭頭解決傳統(tǒng)聲明的函數(shù) this的值在調(diào)用之前難以確定難點存谎。

// HTML
// <div>Hello World!</div>

var ARROW = {
  init: function() {
    this.node = document.body
    this.method()
  },
  method: function () {
    this.node.addEventListener('click', function() {
      // 回調(diào)函數(shù)this的值 
      this.printInfo()
    })
  },
  printInfo: function () {
    console.log(this)
    console.log(this.node)
  }
}

ARROW.init()

上面調(diào)用對象ARROW 的 init 方法拔疚,最為直觀的的感覺就是會執(zhí)行 ARROW 對象內(nèi)部的 printIinfo,但真實的的結(jié)果是會報錯。報錯顯示回調(diào)函數(shù)的 this.printInfo() 不是一個函數(shù)既荚。

在原生JS函數(shù)內(nèi)部的 this 始終指的是當前調(diào)用函數(shù)的這個對象稚失,所以 this.printInfo 中的 this 指向的其實是事件的綁定的節(jié)點,即是 this.node(body),this.node本身是沒有 printInfo這個方法的恰聘。所以會報錯句各。

事件監(jiān)聽的回調(diào)函數(shù)的this的值

如果是為了達到想要的結(jié)果。ARROW.method正確的形式應(yīng)該如下形式

method: function () {
    // that 把 this即是ARROW存儲到method函數(shù)內(nèi)部晴叨。
    var that = this
        this.node.addEventListener('click', function() {
      // that等同于this,而不是this.node
            that.printInfo()
    })
  }

ARROW.method 的回調(diào)函數(shù)改成箭頭函數(shù)的形式,也可以達成上面改進代碼的效果

method: function () {
        this.node.addEventListener('click', () => this.printInfo())
    // 箭頭函數(shù)的this指向與init()方法中this的值形同
  }

在箭頭函數(shù)沒有 this 綁定凿宾,所以箭頭函數(shù)內(nèi)部的 this 值只能通過查找作用域鏈來確定。

箭頭函數(shù)this的值

參考:

《Understanding ECMAScript 6》(簡體中文版)

ECMAScript 6 入門-阮一峰


版權(quán)聲明:本文為博主原創(chuàng)文章兼蕊,未經(jīng)博主許可不得轉(zhuǎn)載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末初厚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子孙技,更是在濱河造成了極大的恐慌产禾,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牵啦,死亡現(xiàn)場離奇詭異下愈,居然都是意外死亡,警方通過查閱死者的電腦和手機蕾久,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拌夏,“玉大人僧著,你說我怎么就攤上這事≌喜荆” “怎么了盹愚?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長站故。 經(jīng)常有香客問我皆怕,道長,這世上最難降的妖魔是什么西篓? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任愈腾,我火速辦了婚禮,結(jié)果婚禮上岂津,老公的妹妹穿的比我還像新娘虱黄。我一直安慰自己,他們只是感情好吮成,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布橱乱。 她就那樣靜靜地躺著辜梳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泳叠。 梳的紋絲不亂的頭發(fā)上作瞄,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音危纫,去河邊找鬼宗挥。 笑死,一個胖子當著我的面吹牛叶摄,可吹牛的內(nèi)容都是我干的属韧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蛤吓,長吁一口氣:“原來是場噩夢啊……” “哼宵喂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起会傲,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锅棕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淌山,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裸燎,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年泼疑,在試婚紗的時候發(fā)現(xiàn)自己被綠了德绿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡退渗,死狀恐怖移稳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情会油,我是刑警寧澤个粱,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站翻翩,受9級特大地震影響都许,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嫂冻,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一胶征、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桨仿,春花似錦弧烤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莺戒。三九已至,卻和暖如春急波,著一層夾襖步出監(jiān)牢的瞬間从铲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工澄暮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留名段,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓泣懊,卻偏偏與公主長得像伸辟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子馍刮,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355