ES6新增了let命令,用來聲明變量。它的用法相似於var,可是所聲明的變量只在let命令所在的代碼塊內有效javascript
新建index.html,文件內容爲html
<script type="text/javascript"> { var a = 12; } console.log(a); </script>
從console中能夠打印出a的值java
在ES6中,使用let聲明a的值,而後再次打印a的值,會報錯python
<script type="text/javascript"> { let a = 12; } console.log(a); </script>
報錯以下所示,程序員
上面兩個例子中,分別用let和var聲明瞭兩個變量。而後在代碼塊以外調用這兩個變量,結果let聲明的變量報錯,var聲明的變量返回了正確的值。這代表,let聲明的變量只在它所在的代碼塊有效編程
修改上面的代碼:瀏覽器
<script type="text/javascript"> { var a = 12; var a = 20; } console.log(a); </script>
結果以下函數
一樣的把上面的var改成let,學習
<script type="text/javascript"> { let a = 12; let a = 20; } console.log(a); </script>
刷新瀏覽器後能夠看到,拋出的異常又不同了this
由於let聲明的變量是塊級做用域,不能重複聲明
再次修改上面的代碼
<script type="text/javascript"> var a = []; for(var i=0;i <10;i++){ a[i] = function () { console.log(i); }; } a[6](); </script>
刷新瀏覽器,獲得的結果爲:
修改代碼,把var改成let
<script type="text/javascript"> var a = []; for(let i=0;i <10;i++){ a[i] = function () { console.log(i); }; } a[6](); </script>
再次刷新瀏覽器,獲得的結果爲:
上面代碼中,變量i是let聲明的,當前的i只在本輪循環有效,因此每一次循環的i其實都是一個新的變量,因此最後輸出的是6。
若是每一輪循環的變量i都是從新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是由於 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i時,就在上一輪循環的基礎上進行計算
修改代碼
<script type="text/javascript"> console.log(foo); var foo = 2; </script>
刷新瀏覽器後,獲得的結果爲
一樣的,把var改成let,又會出現異常
var命令會發生」變量提高「現象,即變量能夠在聲明以前使用,值爲undefined。按照通常的邏輯,變量應該在聲明語句以後纔可使用。
爲了糾正這種現象,let命令改變了語法行爲,它所聲明的變量必定要在聲明後使用,不然報錯。
上面代碼中,變量foo用var命令聲明,會發生變量提高,即腳本開始運行時,變量foo已經存在了,可是沒有值,因此會輸出undefined。變量bar用let命令聲明,不會發生變量提高。
這表示在聲明它以前,變量bar是不存在的,這時若是用到它,就會拋出一個錯誤。
ES5 只有全局做用域和函數做用域,沒有塊級做用域,這帶來不少不合理的場景。
<script type="text/javascript"> var tmp = new Date(); console.log(tmp) function f() { console.log(tmp); if(false){ var tmp = "hello world" } } f(); </script>
程序執行結果
上面代碼的原意是,if代碼塊的外部使用外層的tmp變量,內部使用內層的tmp變量。可是,函數f執行後,輸出結果爲undefined,緣由在於變量提高,致使內層的tmp變量覆蓋了外層的tmp變量。
<script type="text/javascript"> var str = "hello"; for(var i=0;i < str.length;i ++){ console.log(str[i]) } console.log(i) </script>
執行結果:
傳統的JavaScript語言,輸出很長的信息時,一般都是使用"+"號進行拼接的。
這種方法至關繁瑣不方便,ES6引入了模板字符串解決這個問題
模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量
上面代碼中的模板字符串,都是用反引號表示。若是在模板字符串中須要使用反引號,則前面要用反斜槓轉義。
執行結果:
ES6容許使用"箭頭"(=>)定義函數
var f = a => a 等同於 var f = function(a){ return a; }
若是箭頭函數不須要參數或須要多個參數,就使用括號表明參數部分
//無參函數 var f = () => 5; 等同於 var f = function(){return 5}; //多個形參的函數 var f = (num1,num2) => num1 + num2 等同於 var f = function(num1,num2){ return num1 + num2; }
使用箭頭函數須要注意的點:
代碼:
<script type="text/javascript"> var animal = { name:"小狗", age:3, fav:function () { // this是使用時定義的對象 console.log(this); console.log(this.name); } }; animal.fav(); </script>
執行結果:
使用箭頭函數定義上面的函數
<script type="text/javascript"> var animal = { name:"小狗", age:3, fav: ()=>{ // this指向定義時所在的對象(window) console.log(this); console.log(this.name); } }; animal.fav(); </script>
執行結果:
再次修改上面的代碼,打印函數傳遞的參數arguments
<script type="text/javascript"> var animal = { name:"小狗", age:3, fav:function () { // 沒有使用箭頭函數,可使用arguments獲取傳遞的參數 console.log(arguments); console.log(this.name); } }; animal.fav(2,3,4); </script>
執行結果:
使用箭頭函數定義上面的fav函數,再次打印函數傳遞的參數arguments
<script type="text/javascript"> var animal = { name:"小狗", age:3, fav: () => { // 使用箭頭函數時,arguments沒法使用 console.log(arguments); console.log(this.name); } }; animal.fav(2,3,4); </script>
執行結果
爲了解決箭頭函數this指向的問題 推出來一種寫法 對象的單體模式
程序執行結果:
<script type="text/javascript"> function Animal(name, age) { this.name = name; this.age = age; } Animal.prototype.showName = function () { console.log(this.name) } var dog = new Animal("dog", 2); console.log(dog.name); console.log(dog.age); </script>
上面這種寫法跟傳統的面嚮對象語言(好比 Java 和 python)差別很大,很容易讓新學習這門語言的程序員感到困惑。
ES6 提供了更接近傳統語言的寫法,引入了 Class(類)這個概念,做爲對象的模板。
經過class關鍵字,能夠定義類。ES6 的class能夠看做只是一個語法糖,它的絕大部分功能,ES5 均可以作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。
修改上面的代碼,用class建立對象
<script type="text/javascript"> class Animal { // 相似於python中的__init__方法 constructor(name, age) { this.name = name; this.age = age; } showName() { console.log(this.name); } } var d = new Animal("dog", 3); d.showName(); </script>
程序執行結果
上面代碼定義了一個「類」,能夠看到裏面有一個constructor方法,這就是構造方法,而this關鍵字則表明實例對象。
也就是說,ES5 的構造函數Animal,對應 ES6 的Animal類的構造方法。
Animal類除了構造方法,還定義了一個showName方法。注意,定義"類"的方法的時候,前面不須要加上function這個關鍵字,直接把函數定義放進去了就能夠了。另外,方法之間不須要逗號分隔,加了會報錯。
上面代碼表示,類自己就指向了類的構造函數。
使用的時候,也是直接對類使用new命令,跟構造函數的用法徹底一致。
constructor方法是類的默認方法,經過new命令生成對象實例時,自動調用該方法。
一個類必須有constructor方法,若是沒有顯式定義,一個空的constructor方法會被默認添加。
class Animal { } // 等同於 class Animal { constructor() {} }
上面代碼中,定義了一個空的類Point,JavaScript 引擎會自動爲它添加一個空的constructor方法。