ES6核心內容精講--快速實踐ES6(一)

来源:http://www.cnblogs.com/ang-/archive/2017/05/24/6894366.html
-Advertisement-
Play Games

前言 本文大量參考了阮一峰老師的開源教程 "ECMAScript6入門" ,適合新手入門或者對ES6常用知識點進行全面回顧,目標是以較少的篇幅涵蓋ES6及部分ES7在實踐中的絕大多數使用場景。更全面、更深入的請進入上面的教程。如果您覺得有遺漏的常見知識點或者錯誤的地方,請評論指出! 新的變數聲明方式 ...


前言

本文大量參考了阮一峰老師的開源教程ECMAScript6入門,適合新手入門或者對ES6常用知識點進行全面回顧,目標是以較少的篇幅涵蓋ES6及部分ES7在實踐中的絕大多數使用場景。更全面、更深入的請進入上面的教程。如果您覺得有遺漏的常見知識點或者錯誤的地方,請評論指出!

新的變數聲明方式let和const

是什麼:

新的變數聲明方式,提供變數的塊級作用域,同時通過一些限制來更防止我們犯錯誤。也就是說是更好的聲明變數的方式

怎麼用

1)let/const與var的區別是提供了塊級作用域與不再具備變數提升(hoisting)

2)在同一個作用域內let/const禁止重覆聲明相同的變數

var a = 1
let a = 2 // SyntaxError

3)let聲明的變數可重新賦值,const聲明的變數不能重新賦值,即常量。

4)暫時性死區:在當前作用域,使用的變數已經存在,但是在代碼執行到變數聲明前禁止訪問。

var tmp = 123

if (true) {
  tmp = 'abc' // ReferenceError
  let tmp
}

常見使用場景

1)因為能創建塊級作用域,所以常見於if和for中

for (let i = 0; i < arr.length; i++) {
    console.log(arr[i])
}

2)const在實踐中常用來聲明一個對象,之後可以再對這個對象的屬性進行修改

const foo = {
    name: 'bar'
}

foo.name = 'baz'

console.log(foo)

解構

是什麼:

按照阮一峰大神的說法:ES6允許按照一定模式,從數組和對象中提取值,對變數進行賦值,這被稱為解構(Destructuring)。也就是說通過模式匹配來進行變數賦值。

怎麼用:

1)數組基本用法

let [a, b, c] = [1, 2, 3]

a //1
b //2
c //3

2)對象基本用法

let { foo, bar } = { foo: "aaa", bar: "bbb" }
foo // "aaa"
bar // "bbb"

3)函數參數的解構賦值

如在vuex中action不使用解構如下:

actions: {
    increment (context) {
      context.commit('increment')
    }
}

使用解構

actions: {
    increment ({ commit }) {
      commit('increment')
    }
}

4)支持不完全解構

let [foo, bar] = [1, 2, 3]

5)如果解構不成功,變數的值就等於undefined,同時解構賦值允許指定預設值,預設值生效的條件是對象的屬性值嚴格等於undefined。

常見使用場景

1)交換變數的值

[x, y] = [y, x]

2)提取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]

3)函數參數的預設值

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

4)指定載入模塊的什麼功能

import { mapActions } from 'vuex'

箭頭函數

幹嘛的:

箭頭函數可以用來替換函數表達式,不用寫function,更加簡化。也就是說是函數表達式的簡化方式

怎麼用:

1)註意箭頭函數中的this指向外層的this

2)無法用call/apply/bind來改變this指向。

3)在ES6中,會預設採用嚴格模式,因此預設情況下this不是指向window對象,而是undefined。

<script type="text/javascript">
    setTimeout(() => console.log(this), 1000) // undefined,不是window
</script>

4)不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用rest參數代替。

使用場景:

關鍵是你需要this指向什麼

預設參數和rest參數

是什麼:

預設參數就是設置參數預設值,rest參數(翻譯為不具名參數,也叫做剩餘參數)是將傳入的未具名的參數作為一個數組集合

怎麼用:

如下,預設參數給參數賦一個預設值,rest參數使用三個點(...)加數組集合名

function foo(arg1 = 1, ...restArg){
    console.log(arg1, restArg)
}

foo(undefined, 2, 3, 4) // 1, [2, 3, 4]

foo(2, 3, 4) // 2, [3, 4]

擴展運算符

是什麼:

同rest參數一樣,也是三個點。它好比rest參數的逆運算,將一個數組轉為用逗號分隔的參數序列。因此常用於函數調用。

常見使用場景:

1)合併數組

let newArr = [...arr1, ...arr2, ...arr3]

2)與解構賦值結合

// ES5
a = list[0], rest = list.slice(1)

// ES6
[a, ...rest] = list

3)將字元串轉為數組

[...'test'] // [ "t", "e", "s", "t"]

對象擴展

語法變化

1)屬性簡寫,當對象的一個屬性名稱與本地變數名相同的時候,可以省略冒號和值

var foo = 'bar'
var baz = {foo}
baz // {foo: "bar"}

2)屬性名錶達式,可以在以對象字面量方式定義對象是使用表達式作為屬性名

// ES5只能這樣
obj['a' + 'bc'] = 123 

// ES6還能這樣
let obj = {
  ['a' + 'bc']: 123
}

3)方法簡寫,省去:和function

const foo = {
  bar () {
    console.log('1')
  }
}

Object.is()

更好的判斷方法,與===的不同有兩點:一是+0不等於-0,二是NaN等於自身。

NaN === NaN // false
Object.is(NaN, NaN) // true

Object.assign()

1)Object.assign方法用於對象的合併,用法與jQuery和underscore的extend方法類似,而且同樣會改變target。

Object.assign(target, source1, source2)

2)只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)。

3)Object.assign方法實行的是淺拷貝,而不是深拷貝。

Object.setPrototypeOf

用來設置一個對象的prototype對象,返回參數對象本身

Object.setPrototypeOf(object, prototype)

Object.getPrototypeOf()

Object.getPrototypeOf方法可以用來從子類上獲取父類。因此,可以使用這個方法判斷,一個類是否繼承了另一個類。參見下麵類與繼承章節

遍歷

對象的每個屬性都有一個描述對象(Descriptor),Object.getOwnPropertyDescriptor方法可以獲取該屬性的描述對象。這個描述對象有value、writable、enumerable、configurable四大屬性。

ES5下麵三個操作會忽略enumerable為false的屬性。

  • for...in迴圈:只遍歷對象自身的和繼承的可枚舉的屬性
  • Object.keys():返回對象自身的所有可枚舉的屬性的鍵名
  • JSON.stringify():只串列化對象自身的可枚舉的屬性

ES6新增的操作Object.assign(),也會忽略enumerable為false的屬性,只拷貝對象自身的可枚舉的屬性。

ES6一共有5種方法可以遍歷對象的屬性。

(1)for...in

for...in迴圈遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)。

(2)Object.keys(obj)

Object.keys返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含Symbol屬性)。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一個數組,包含對象自身的所有屬性(不含Symbol屬性,但是包括不可枚舉屬性)。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一個數組,包含對象自身的所有Symbol屬性。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一個數組,包含對象自身的所有屬性,不管屬性名是Symbol或字元串,也不管是否可枚舉。

以上的5種方法遍歷對象的屬性,都遵守同樣的屬性遍歷的次序規則。

  • 首先遍歷所有屬性名為數值的屬性,按照數字排序。
  • 其次遍歷所有屬性名為字元串的屬性,按照生成時間排序。
  • 最後遍歷所有屬性名為Symbol值的屬性,按照生成時間排序。

大多數時候,我們只關心對象自身的可枚舉屬性。所以,儘量不要用for...in迴圈,而用Object.keys()代替。

字元串擴展

以前判斷一個字元串是否包含某個字元串只能通過indexOf的值是否大於-1來判斷,現在新增了三種方法:

includes():表示是否包含該字元串。

startsWith():表示該字元串是否在頭部。

endsWith():表示該字元串是否在尾部。

'hello world'.includes('hello') // true

模板字元串

幹嘛的:

和handlebars那些模板引擎功能類似,有模板字元串可以不用拼接字元串了

怎麼用:

用反引號``將整個字元串包裹起來,${}表示一個變數或者一個表達式,可以嵌套

const tmpl = addrs => `
  <table>
  ${addrs.map(addr => `
    <tr><td>${addr.first}</td></tr>
    <tr><td>${addr.last}</td></tr>
  `).join('')}
  </table>
`

const data = [
  { first: 'Jane', last: 'Bond' },
  { first: 'Lars', last: 'Croft' },
]

console.log(tmpl(data))

標簽模板

函數名後面緊接一個模板字元串。該函數將被調用來處理這個模板字元串。這被稱為“標簽模板”功能(tagged template)。當字元串模板有變數時,函數的第一個參數為被變數分開的字元串組成的數組,後面的參數依次為變數,這些變數的參數序列可以使用rest參數。

var a = 5
var b = 10

tag`Hello ${ a + b } world ${ a * b }`
// 等同於
tag(['Hello ', ' world ', ''], 15, 50)

數組擴展

Array.of()

Array.of方法用於將一組值,轉換為數組。可以替代Array,且其行為非常統一,不像Array只有一個正整數參數n時,會生成n個空位構成的數組

Array.of(1) // [1]
Array.of(1, 2, 3) // [1, 2, 3]
Array(1) // [undefined * 1],其實不是undefined,是空位,如下可證明兩者並不一樣
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
Array(1, 2, 3) // [1, 2, 3]

Array.from()

Array.from方法用於將兩類對象轉為真正的數組:類數組對象(array-like object)和可遍歷(iterable)對象(包括ES6新增的數據結構Set和Map)。Array.from還可以接受第二個參數,作用類似於數組的map方法,用來對每個元素進行處理,將處理後的值放入返回的數組。

Array.from({'0': 'a', length: 1}) // ['a']

Array.from('hello') // ['h', 'e', 'l', 'l', 'o'],因為字元串有Iterator介面,可遍歷

Array.from([1, 2, 3], (x) => x * x) // [1, 4, 9]

常見使用場景:

1)轉換NodeList集合。常見的類似數組的對象是DOM操作返回的NodeList集合,以及函數內部的arguments對象。但是後者使用rest參數更簡便

// NodeList對象
let elementDivList = document.querySelectorAll('div')
Array.from(elementDivList).forEach(function (div) {
  console.log(div)
})

2)數組去重。與下麵要講到的Set配合即可很簡單地實現數值去重。

var arr = [1, 3, 5, 5, 8, 3, 2]
var uniqueArr = Array.from(new Set(arr))
console.log(uniqueArr) // [1, 3, 5, 8, 2]

數組實例的copyWithin方法

Array.prototype.copyWithin(target, start = 0, end = this.length)

它接受三個參數。

  • target(必需):從該位置開始替換數據。
  • start(可選):從該位置開始讀取數據,預設為0。如果為負值,表示倒數。
  • end(可選):到該位置前停止讀取數據,預設等於數組長度。如果為負值,表示倒數。
    [1, 2, 3, 4, 5].copyWithin(0,2) // [3, 4, 5, 4, 5]
    /* 從索引2開始讀取數據,到數組尾部停止,即讀到(3, 4, 5),然後從索引0開始替換數據 */

數組實例的find和findIndex方法

找到第一個符合條件的item(項)或index(索引),前者相當於underscore中的first方法,後者則和underscore中的同名方法一致。另外,這兩個方法都可以藉助Object.is發現NaN,彌補了數組的IndexOf方法的不足。

[1, 2, 3, 4].find(x => x > 2) // 3
[1, 2, 3, 4].findIndex(x => x > 2) // 2
[NaN].findIndex(x => Object.is(NaN, x)) // 0

數組實例的fill方法

Array.prototype.fill(fillItem, start = 0, end = this.length)

[1, 3, 6, 11, 4].fill(10,2) // [1, 3, 10, 10, 10]

數組實例的includes方法

與字元串的includes方法類似。該方法屬於ES7,但Babel轉碼器已經支持。

[1, 2, 3].includes(3, 3) // false
[1, 2, 3].includes(3, -1) // true
[NaN].includes(NaN) // true

Set和Map

ES6中增加了兩個新的數據結構:Set和Map。Set是不包含重覆值的列表,而Map則是鍵與相對應的值的集合。

Set

是什麼:

Set是不包含重覆值的有序列表。

怎麼用:

1)Set構造函數可以接受一個數組(或類似數組的對象)作為參數,用來初始化。

const set = new Set([1, 2, 3, 4, 4])
console.log(set)

2)四個操作方法(add()、delete()、has()、clear())和一個屬性(size),使用方法根據名字和下麵例子就知道了

const s = new Set()
s.add(1).add(2).add(2) // 註意2被add了兩次

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2)
s.has(2) // false

s.add(3)
s.size // 2

s.clear()
s.size // 0

3)三個遍歷器生成函數(keys()、values()、entries())和一個遍歷方法(forEach())

keys方法、values方法、entries方法返回的都是遍歷器對象(詳見Iterator)。都這可以使用遍歷器對象的方法for...of進行遍歷。由於 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以keys方法和values方法的行為完全一致。forEach方法與ES5數組的forEach類似。

let set = new Set(['red', 'green', 'blue'])

for (let item of set.keys()) {
  console.log(item)
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item)
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item)
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

set.forEach((value, key) => console.log(value, key))

4)Set轉化為數組,有兩種方法:...擴展運算符和Array.from()

這兩者可互換,因此前面提到的使用Array.from()來數組去重也可以這樣做:[...new Set(arr)]

// 方法一
let set = new Set([1, 2, 3])
set = new Set([...set].map(val => val * 2))
// set的值是2, 4, 6

// 方法二
let set = new Set([1, 2, 3])
set = new Set(Array.from(set, val => val * 2))
// set的值是2, 4, 6

Map

是什麼:

一種由鍵值對集合構成的數據結構,類似於對象,但是“鍵”的範圍不限於字元串,各種類型的值(包括對象)都可以當作鍵。

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

怎麼用:

1)Set構造函數可以接收任何一個具有Iterator介面的數據結構作為參數

const set = new Set([
  ['foo', 1],
  ['bar', 2]
])
const m1 = new Map(set)
m1.get('foo') // 1

2)5個操作方法(set(key, value)、get(key)、has(key)、delete(key)、clear())和一個屬性(size)

3)遍歷生成函數和遍歷方法和Set類似,Map結構的預設遍歷器介面(Symbol.iterator屬性),就是entries方法。

map[Symbol.iterator] === map.entries // true

4)Map轉為數組,使用...擴展運算符

WeakSet和WeakMap

WeakSet、WeakMap分別和Set、Map類似,不過存儲的是對象的弱引用方式,這樣在記憶體管理上更加容易優化。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這個模式主要由 命令類、用戶請求數據類、業務邏輯類、命令類工廠類及調用類構成,各個類的作用概括如下: 1、命令類:調用用戶請求數據類和業務邏輯類; 2、用戶請求數據類:獲取用戶請求數據及保存後臺處理後返回的結果; 3、業務邏輯類:如以下的示例中驗證用戶登陸信息是否正確的功能等; 4、命令工廠類(我自 ...
  • 聲明:我使用的Elasticsearch的版本是5.4.0,安裝分詞器前請先安裝maven 一:安裝maven https://github.com/apache/maven 說明: 安裝maven需要java1.7+ 編譯安裝分詞器時,可能會報錯,報錯信息如下: [ERROR] COMPILATI ...
  • 什麼是持續集成:http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html 持續集成的好處:https://zhuanlan.zhihu.com/p/20589465?columnSlug=jishuqushi 本人之前待過的 ...
  • 1 #include 2 #include 3 4 using namespace std; 5 6 7 class Handler 8 { 9 public: 10 Handler(Handler* pstHandler): m_pstHandler(pstHandler) 11 { 12 13 ... ...
  • --save參數表示將該模塊寫入dependencies屬性, --save-dev表示將該模塊寫入devDependencies屬性。 devDependencies指定項目開發所需要的模塊。 ...
  • 1 快捷方式:html:xt +tab 過渡XHTML html:xs+tab 嚴格XHTML !+tab html5的標簽結構 2.Charset 編碼 <meta charset="UTF-8"> Ascll Ansi Unicode Gbk 包含全部中文字元 繁體 Gb2312 簡單中文 Bi ...
  • 筆者在查詢bootstrap table資料的時候,看了很多文章,發覺很多文章都寫了關於如何使用bootstrap table的例子,當然最好的例子還是官網。但是對於某部分技術人員來說,入門還是不夠詳細,故有了下列的文章。希望我的文章能給大家帶來幫助。 bootstrap-table作為常用的TAB ...
  • 原文參考http://mp.weixin.qq.com/s/LijjPErxcFB4pN_wUo2cnw 調用函數時,會創建一個新的執行上下文 它的生命周期有兩個階段1創建階段-創建變數對象,建立作用域鏈,確定this的指向2執行階段-執行代碼,完成變數賦值,函數引用及其他代碼的執行 變數對象的創建 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...