ES6特性解釋

let和const

  • let在塊級作用域有效。不存在之前的var的作用域提升。
  • const意思是隻讀的變量。不可以在聲明之後再改變值。
  • const指向對象的時候,對象可以改變屬性,但是對象不能變。
{
    let a=1;
}
for(let i=0;i<10;i++){
}

變量的解構

1.數組的解構。

  • 左邊的變量對等於右邊的值。
  • 值的長度可變,不存在則等於undefined
  • 右邊的結構要求實現Iterator ,數組、Set都算。
  • -可以在定義之前指定默認值,如果右邊不存在則使用默認值,(null也算賦值)
let [a, b, c] = [1, 2, 3];
let [x, y, z] = new Set(['a', 'b', 'c']);
let [foo = true] = [];

2.對象的解構

  • 變量名等於屬性名對應的值
  • 可以指定對象名對應的值
let { foo, bar } = { foo: "aaa", bar: "bbb" };
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

3.字符串也可以解構

const [a, b, c, d, e] = 'hello';
let {length : len} = 'hello';

4.函數參數的解構

function add([x, y]){
  return x + y;
}
add([1, 2]); // 3

5.解構的表達式中不能使用圓括號’()’,一旦使用就會報錯

字符串新方法

  • “\u{41}\u{42}\u{43}”表示法
  • codePointAt獲取字符串的十進制
  • fromCodePoint從進制轉字符串
  • for…of接口
  • at返回下標對應的字符
  • normalize
  • includes、startsWith、endsWith
  • repeat
  • padStart、padEnd補全
  • 模板字符串aaa${name}
  • 標籤模板
  • String.rawHi\n${2+3}!

以上做一個備註

正則的擴展

  • new RegExp(/abc/ig, ‘i’)
  • String.prototype.match調用RegExp.prototype[Symbol.match]
  • u修飾符
var result = text.match(/[\s\S]/gu);
  return result ? result.length : 0;
  //返回中文字符串的正確長度
  • y修飾符
  • sticky
  • flags
  • s修飾符

數值擴展

  • 0b二進制和0o八進制表示法
  • Number.isFinite()和Number.isNaN()
  • Number.parseInt(), Number.parseFloat()
  • Number.isInteger()是否爲整數
  • Number.EPSILON常量
  • Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER上下限
  • Math.trunc()去掉小數部分
  • Math.sign()正負數判斷
  • Math.cbrt() 計算立方根
  • Math.clz32()
  • Math.imul()
  • Math.fround()
  • Math.hypot()
  • Math.expm1()
  • Math.log1p()
  • Math.log10()
  • Math.log2()
  • 指數運算符**

函數的擴展

  • 函數參數默認值,默認值在最後
  • length返回沒有默認值的參數個數
  • rest 參數(形式爲…變量名)
  • name返回函數名稱
  • 箭頭函數。
var f = () => 5;
// 等同於
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同於
var sum = function(num1, num2) {
  return num1 + num2;
};
1.函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
2.不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
3.不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
4.不可以使用yield命令,因此箭頭函數不能用作 Generator 函數。
  • ::綁定 this
  • 尾調用,優化

數組的擴展

  • 擴展運算符…
  • Array.from將類似數組(包含length屬性)和實現了Iterable的對象轉爲數組。第二個參數是處理方法
  • Array.of()將參數轉爲數組
  • copyWithin(開始位置,開始讀取位置,結束讀取位置)
  • find,findIndex
  • fill(填充值,開始位置,結束位置)
  • entries(),keys() 和 values()
  • includes(是否包含的值,開始查詢的位置)

屬性的擴展

  • 屬性的簡潔表示法
  • 字面量定義對象,不能同時使用簡潔表示法
let propKey = 'foo';

let obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};
  • 方法的 name 屬性
  • Object.is()
  • Object.assign()

    1.for…in循環遍歷對象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。
    2.Object.keys返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)
    3.Object.getOwnPropertyNames返回一個數組,包含對象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)。
    4.Object.getOwnPropertySymbols返回一個數組,包含對象自身的所有 Symbol 屬性。
    5.Reflect.ownKeys返回一個數組,包含對象自身的所有屬性,不管屬性名是 Symbol 或字符串,也不管是否可枚舉。

  • Object.getOwnPropertyDescriptors()

  • Object.create
  • Object.setPrototypeOf()和Object.getPrototypeOf()
  • Object.keys(),Object.values(),Object.entries()
  • 對象的擴展運算符…

Symbol

ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。它是 JavaScript 語言的第七種數據類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)。

let s = Symbol();
typeof s
// "symbol"

var mySymbol = Symbol();

// 第一種寫法
var a = {};
a[mySymbol] = 'Hello!';

// 第二種寫法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三種寫法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"
  • Object.getOwnPropertySymbols可以獲取到對象的Symbol屬性
  • Symbol.for(),Symbol.keyFor()

Set和Map

Set

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4
  • Set.prototype.constructor:構造函數,默認就是Set函數。
  • Set.prototype.size:返回Set實例的成員總數。
  • add(value):添加某個值,返回Set結構本身。
  • delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
  • has(value):返回一個布爾值,表示該值是否爲Set的成員。
  • clear():清除所有成員,沒有返回值。
  • keys():返回鍵名的遍歷器
  • values():返回鍵值的遍歷器
  • entries():返回鍵值對的遍歷器
  • forEach():使用回調函數遍歷每個成員

WeakSet

1.WeakSet 的成員只能是對象,而不能是其他類型的值。
2.WeakSet 中的對象都是弱引用,即垃圾回收機制不考慮 WeakSet 對該對象的引用

Map

const map = new Map([
  ['name', '張三'],
  ['title', 'Author']
]);

map.size // 2
map.has('name') // true
map.get('name') // "張三"
map.has('title') // true
map.get('title') // "Author"
  • keys():返回鍵名的遍歷器。
  • values():返回鍵值的遍歷器。
  • entries():返回所有成員的遍歷器。
  • forEach():遍歷 Map 的所有成員。

WeakMap

1.WeakMap只接受對象作爲鍵名(null除外),不接受其他類型的值作爲鍵名。
2.WeakMap的鍵名所指向的對象,不計入垃圾回收機制。

WeakMap 與 Map 在 API 上的區別主要是兩個,一是沒有遍歷操作(即沒有key()、values()和entries()方法),也沒有size屬性。因爲沒有辦法列出所有鍵名,某個鍵名是否存在完全不可預測,跟垃圾回收機制是否運行相關。這一刻可以取到鍵名,下一刻垃圾回收機制突然運行了,這個鍵名就沒了,爲了防止出現不確定性,就統一規定不能取到鍵名。二是無法清空,即不支持clear方法。因此,WeakMap只有四個方法可用:get()、set()、has()、delete()。

Proxy

1.get(target, propKey, receiver)
2.set(target, propKey, value, receiver)
3.has(target, propKey)
4.deleteProperty(target, propKey)。用於攔截delete操作
5.ownKeys(target)
6.getOwnPropertyDescriptor(target, propKey)
7.defineProperty(target, propKey, propDesc)。攔截了Object.defineProperty操作
8.preventExtensions(target)
9.getPrototypeOf(target)
10.isExtensible(target)
11.setPrototypeOf(target, proto)
12.apply(target, object, args)
13.construct(target, args)。方法用於攔截new命令

Reflect

1.將Object對象的一些明顯屬於語言內部的方法(比如Object.defineProperty),放到Reflect對象上。現階段,某些方法同時在Object和Reflect對象上部署,未來的新方法將只部署在Reflect對象上。也就是說,從Reflect對象上可以拿到語言內部的方法。
2.修改某些Object方法的返回結果,讓其變得更合理。比如,Object.defineProperty(obj, name, desc)在無法定義屬性時,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)則會返回false。

  • Reflect.apply(target,thisArg,args)
  • Reflect.construct(target,args)
  • Reflect.get(target,name,receiver)
  • Reflect.set(target,name,value,receiver)
  • Reflect.defineProperty(target,name,desc)
  • Reflect.deleteProperty(target,name)
  • Reflect.has(target,name)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

Promise

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

Iterator(遍歷器)

1.創建一個指針對象,指向當前數據結構的起始位置。也就是說,遍歷器對象本質上,就是一個指針對象。
2.第一次調用指針對象的next方法,可以將指針指向數據結構的第一個成員。
3.第二次調用指針對象的next方法,指針就指向數據結構的第二個成員。
4.不斷調用指針對象的next方法,直到它指向數據結構的結束位置。

const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

Generator

Generator 函數有多種理解角度。從語法上,首先可以把它理解成,Generator 函數是一個狀態機,封裝了多個內部狀態。

執行 Generator 函數會返回一個遍歷器對象,也就是說,Generator 函數除了狀態機,還是一個遍歷器對象生成函數。返回的遍歷器對象,可以依次遍歷 Generator 函數內部的每一個狀態。

形式上,Generator 函數是一個普通函數,但是有兩個特徵。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不同的內部狀態(yield在英語裏的意思就是“產出”)。

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();

yield 表達式

(1)遇到yield表達式,就暫停執行後面的操作,並將緊跟在yield後面的那個表達式的值,作爲返回的對象的value屬性值。

(2)下一次調用next方法時,再繼續往下執行,直到遇到下一個yield表達式。

(3)如果沒有再遇到新的yield表達式,就一直運行到函數結束,直到return語句爲止,並將return語句後面的表達式的值,作爲返回的對象的value屬性值。

(4)如果該函數沒有return語句,則返回的對象的value屬性值爲undefined。

需要注意的是,yield表達式後面的表達式,只有當調用next方法、內部指針指向該語句時纔會執行,因此等於爲 JavaScript 提供了手動的“惰性求值”(Lazy Evaluation)的語法功能。

async

var fs = require('fs');

var readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) return reject(error);
      resolve(data);
    });
  });
};

var gen = function* () {
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};
//等同於
var asyncReadFile = async function () {
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

Class

//定義類
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
   static classMethod() {
    return 'hello';
  }
}
//繼承
class Point {
}

class ColorPoint extends Point {
}

類的修飾

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

Module 的語法

import { stat, exists, readFile } from 'fs';

ES6 的模塊自動採用嚴格模式,不管你有沒有在模塊頭部加上”use strict”;。

嚴格模式主要有以下限制。

  • 變量必須聲明後再使用
  • 函數的參數不能有同名屬性,否則報錯
  • 不能使用with語句
  • 不能對只讀屬性賦值,否則報錯
  • 不能使用前綴0表示八進制數,否則報錯
  • 不能刪除不可刪除的屬性,否則報錯
  • 不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]
  • eval不會在它的外層作用域引入變量
  • eval和arguments不能被重新賦值
  • arguments不會自動反映函數參數的變化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局對象
  • 不能使用fn.caller和fn.arguments獲取函數調用的堆棧
  • 增加了保留字(比如protected、static和interface)

上面這些限制,模塊都必須遵守。由於嚴格模式是 ES5 引入的,不屬於 ES6,所以請參閱相關 ES5 書籍

其中,尤其需要注意this的限制。ES6 模塊之中,頂層的this指向undefined,即不應該在頂層代碼使用this。

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