《ES6入門》學習筆記

ES6和ECMAScript2015的關係

標準委員會最終決定,標準在每年的 6 月份正式發佈一次,作爲當年的正式版本。接下來的時間,就在這個版本的基礎上做改動,直到下一年的 6 月份,草案就自然變成了新一年的版本。這樣一來,就不需要以前的版本號了,只要用年份標記就可以了。

ES6 的第一個版本,就這樣在 2015 年 6 月發佈了,正式名稱就是《ECMAScript 2015 標準》(簡稱 ES2015)。2016 年 6 月,小幅修訂的《ECMAScript 2016 標準》(簡稱 ES2016)如期發佈,這個版本可以看作是 ES6.1 版,因爲兩者的差異非常小(只新增了數組實例的includes方法和指數運算符),基本上是同一個標準。根據計劃,2017 年 6 月發佈 ES2017 標準。


Babel轉碼器

Babel是一個廣泛使用的ES6轉碼器,可以將ES6代碼轉爲ES5代碼,從而在現有的環境執行

// 轉碼前
input.map(item => item + 1);

// 轉碼後
input.map(function (item) {
  return item + 1;
});

Babel的配置文件是.babelrc,存放在根目錄下,該文件來設置轉碼規則和插件

{
  "presets": [],
  "plugins": []
}

命令行轉碼babel-cli

安裝命令如下

$ npm install --global babel-cli

 改寫package.json

{
  // ...
  "devDependencies": {
    "babel-cli": "^6.0.0"
  },
  "scripts": {
    "build": "babel src -d lib"
  },
}

babel-node命令,提供一個支持ES6的REPL環境,支持Node的REPL環境的所有功能,而且可以直接執行ES6 。

babel-register模塊改寫require命令,加上一個鉤子。每當使用require加載.js .jsx .es .es6後綴名的文件就會先用Babel轉碼。

babel-core模塊,對需要調用Babel的API進行轉碼。

babel-polyfill爲當前環境提供一個墊片,比如IteratorGeneratorSetMapProxyReflectSymbolPromise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)進行轉碼。


let和const命令

ES6新增了let命令用來聲明變量,用法類似與var,但所生命的變量在let命令所在的代碼塊內有效。

for循環的計數器模式和使用let命令。

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10


var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

不存在變量提升

// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;

暫時性死區

在代碼塊內,使用lei命令聲明變量之前,該變量都是不可用的

if (true) {
  // TDZ開始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ結束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

 

let不允許在相同作用域內,重複聲明同一個變量 。

function func(arg) {
  let arg; // 報錯
}

function func(arg) {
  {
    let arg; // 不報錯
  }
}

塊級作用域

ES5只有全局作用域和函數作用域,沒有塊級作用域會導致內層變量可能覆蓋外層變量,用來計數的循環變量泄露爲全局變量。

塊級作用域的出現使得廣泛應用的立即執行函數表達式不必要了IIFE。

// IIFE 寫法
(function () {
  var tmp = ...;
  ...
}());

// 塊級作用域寫法
{
  let tmp = ...;
  ...
}

考慮到環境導致的行爲差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。

// 函數聲明語句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函數表達式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

const命令

const聲明一個只讀的常量,一旦聲明,常量的值就不能改變

const的作用域與let命令相同:只在聲明所在的塊級作用域內有效。

const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動

const a = [];
a.push('Hello'); // 可執行
a.length = 0;    // 可執行
a = ['Dave'];    // 報錯

可以使用Object。freeze方法將對象凍結

const foo = Object.freeze({});

// 常規模式時,下面一行不起作用;
// 嚴格模式時,該行會報錯
foo.prop = 123;

 變量的解構賦值用途

1.交換變量的值

let x = 1;
let y = 2;

[x, y] = [y, x];

2.從函數返回多個值

// 返回一個數組

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一個對象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

3.函數參數的定義

解構賦值可以方便地將一組參數與變量名對應起來

// 參數是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 參數是一組無次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

4.提取JSON數據

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

5.函數參數默認值

jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};

 6.遍歷Map結構

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world

// 獲取鍵名
for (let [key] of map) {
  // ...
}

// 獲取鍵值
for (let [,value] of map) {
  // ...
}

 7.輸入模塊的指定方法

const { SourceMapConsumer, SourceNode } = require("source-map");

 字符串的擴展

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章