1. 程式人生 > >【新手向】ES6常見概念初體驗

【新手向】ES6常見概念初體驗

一、var和let命令

作用域

 ES5的作用域只有全域性作用域和函式作用域,這會帶來很多問題,比如常用的for迴圈中var宣告的i只作為計數來控制迴圈,但是迴圈結束後i任然存在,因為i的作用域是全域性的。所以我們迴圈計數的標識往往會變成i j k ......,這是我們不希望看到的現象。

for (var i = 0; i < 5; i++) { }
console.log(i); // 5

 ES6中新增了let命令,和var類似都用來宣告變數,但let的作用域是ES6新增的塊級作用域,僅在當前的程式碼塊中有效。

for (let i = 0; i <
5; i++) { } console.log(i); // error let j = 1; if (true) { let j = 2; console.log(j); // 2 } console.log(j); // 1

變數提升

 ES5還存在變數提升的問題,即“函式及變數的宣告都將被提升到函式的最頂部”,在一些規範的JavaScript程式碼中會發現大量的變數都集中在js指令碼檔案的頂部進行宣告,這是為了避免變數提升現象導致的隱患。

console.log(m); // 輸出為 undefined ,並沒有報錯,這說明 m 是存在的
var m = 1;

// 其實上述程式碼因為變數提升而被執行為:
var m; console.log(m); m = 1;

 為了避免變數提升帶來的隱患,let禁止在變數宣告前使用。

console.log(m); // undefined
var m = 1;

console.log(n); // error
let n = 1;

二、const

const同樣是ES6新增的命令,與var let宣告變數不同,const宣告的是常量,const宣告的常量無法改變其值。

const PI = 3.1415;
PI = 1; // error

三、箭頭函式

 ES5中我們常見的匿名函式是這樣的。

function(
) { console.log(1); }

 箭頭函式簡化了這種寫法,去掉了function並在(){}之間添加了=>

() => {
  console.log(1);
}

 如果函式是引數運算等情況的話那麼可以進一步簡化。

function (x) {
  return x * x;
}
// 等同於
x => x * x;

除了簡化ES5寫法之外箭頭函式與匿名函式最大的不同在於修正了this的錯誤指向,詳見廖雪峰的官方網站


四、資料結構Map

Map是ES6新增的資料結構,類似於物件Object,要正確和方法.map()進行區分。
 首先建立一個Object例項來仔細觀察一下Object,其實是我們常說的鍵值對的集合,然而傳統的Object只接受字串作為鍵名。

const element = document.getElementById('myDiv');
person=new Object();
person.firstname="Bill";
person.lastname="Gates";
person[element] = "abc";
console.log(person);
/**
*  {
*    [object HTMLDivElement]: "abc"
*    firstname: "Bill"
*    lastname: "Gates"
*  }
**/
console.log(person['[object HTMLDivElement]']); // "abc"

 可以看到字串'[object HTMLDivElement]'作為鍵成功的匹配到了對應的值abc,然而我們存入的其實是一個DOM節點,怎麼會被字串匹配出來?這說明Object的結構是字串 - 值,也就是將鍵作為字串儲存起來,而我們希望的結構是值 - 值,資料結構Map解決了這個問題。

const element = document.getElementById('myDiv');
person=new Map();
person.firstname="Bill";
person.lastname="Gates";
person.set(element, "abc");
console.log(person.get(element)); // "abc"

 利用Mapset() get()方法進行新增和讀取成員,除此之外還包含size() has() delete() clear()操作方法和keys() values() entries() forEach()遍歷方法。


五、for…of迴圈

for...of迴圈在陣列中較為常用,上文提到的Map結構中也可以使用for...of迴圈。

const arr = [1, 2, 3];
for(let item of arr) {
  console.log(item); // 1 2 3
}

六、Class(類)

Class讓定義類更加簡單,直接看例子。

function Student(name) {
  this.name = name;
}
Student.prototype.hello = function () {
  alert('Hello, ' + this.name + '!');
}
let x = new Student("LiHua");
x.hello(); // Hello,LiHua!

 傳統的ES5我們可以通過上述建構函式的方法生成例項物件,而ES6中可以通過Class來定義類,使其更接近傳統面嚮物件語言。

class Student {
  constructor(name) {
    this.name = name;
  }
  hello() {
    alert('Hello, ' + this.name + '!');
  }
}

 比較一下會發現包含建構函式constructor和函式hello的類Student避免了程式碼的分散,並且更接近傳統面嚮物件語言,降低了學習難度。

Class類的繼承

 新建一個Class類想要繼承之前類的方法也變得更加簡單,只需要通過extends命令即可。

// 父類
class Student {
  constructor(name) {
    this.name = name;
  }
  hello() {
    alert('Hello, ' + this.name + '!');
  }
}
// 子類
class PrimaryStudent extends Student {
  constructor(name, grade) {
    super(name); // 用super呼叫父類的構造方法
    this.grade = grade;
  }
  myGrade() {
    alert('I am at grade ' + this.grade);
  }
}
let x = new PrimaryStudent("LiHua", "Three");
x.hello();
x.myGrade();

七、export 與 import

exportimport的引入為程式碼帶來了模組化的可能,將龐大的程式碼拆成一塊一塊的元件,通過拼裝組合進行使用來完成一些大型專案。

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year}; 
// 通過 export 輸出
import {firstName, lastName, year} from './profile.js';
// 通過 import 引入

更多拓展閱讀 <阮一峰 ECMAScript 6 入門>