歡迎訪問我的博客https://qqqww.com/叮贩,祝碼農同胞們早日走上人生巔峰,迎娶白富美~~~
由于沒寫目錄板鬓,移步https://blog.csdn.net/weixin_43307658/article/details/86698281體驗更好
1 Babel 轉碼
請移步我的另一篇博客ES6-Babel轉碼
2 聲明變量
在
ES6
中常用let
或const
來聲明變量肴甸,下面介紹let
和const
2.1 let
ES6 新增了
let
命令,用來聲明變量腿时。它的用法類似于var
,但是所聲明的變量饭宾,只在let
命令所在的代碼塊內有效
2.1.1 引入 let 的好處
我們在
ES5
中使用var
來聲明變量批糟,但是var
的變量提升
往往會帶來一些問題:
// 使用 var
console.log(a) // 輸出 undefined
var a = 1
// 使用 let
console.log(b) // 輸出 ReferenceError
let b = 1
一般我們認為應該先聲明變量再使用,但是這里使用
var
聲明的變量卻能提前使用看铆,而不報錯徽鼎,本身在邏輯性上可能會覺得不太好,但是還沒有看到具體會引起什么錯誤弹惦,那么再看下面的代碼:
var a = new Date() // Tue Jan 29 2019 20:31:15 GMT+0800 (中國標準時間)
function fn () {
cosole.log(a)
if (false) {
a = 'hello'
console.log(a)
}
}
fn() // undefined
上述代碼由于
if
代碼塊使用內層的變量否淤,外面的使用外層的變量,看似互不影響棠隐,但是由于var
存在變量提升石抡,導致內層的a
覆蓋了外層的a
,甚至有可能將局部變量提升為全局變量助泽,以后有可能引起內存泄漏
所以引入
let
啰扛,let
聲明的變量有自己獨立的作用域塊,let
聲明的變量只在let
所在的塊內起作用嗡贺,不再受外部影響隐解,形成暫時性死區(qū),有效防止變量提升問題暫時性死區(qū):在代碼塊內暑刃,使用
let
命令聲明變量之前厢漩,該變量都是不可用的
我們將上述代碼中的
var
換為let
看看
let a = new Date() // Tue Jan 29 2019 20:31:15 GMT+0800 (中國標準時間)
function fn () {
cosole.log(a)
if (false) {
a = 'hello'
console.log(a)
}
}
fn() // Tue Jan 29 2019 20:31:15 GMT+0800 (中國標準時間)
這時候就不存在變量提升的問題了
2.1.2 let 規(guī)則
使用
let
聲明的變量可以重新賦值,但是不能在同一作用域內重新聲明
2.2 const
const
和let
引入的好處基本一樣,但是為什么還要引入呢岩臣?看看下面的const
規(guī)則:使用
const
聲明的變量必須賦值初始化,但是不能在同一作用域類重新聲明也無法重新賦值它們的區(qū)別就在于規(guī)則,其他幾乎一模一樣
3 模板字面量
ES6
中的模板字面量就是通過一種更加簡便的方法去拼接字符串宵膨,在以前我們常通過+
或者concat()
等方法去拼接字符串
const dog1 = {
name: 'dahuang',
age: 10
}
const dog2 = {
name: 'xiaohei',
age: 10
}
let mes = dog1.name + 'and' + dog2.name + 'are dog'
下面用模板字面量去拼接字符串
let mes = `${dog1.name} and ${dog2.name} are dog`
一對反引號搞定
4 解構賦值
ES6 允許按照一定模式架谎,從數(shù)組和對象中提取值,對變量進行賦值辟躏,這被稱為解構(Destructuring)
以前為變量賦值谷扣,只能直接指定值,下面來自阮一峰老師的文檔里的一個小例子
let a = 1
let b = 2
let c = 3
ES6
允許下面這樣
let [a, b, c] = [1, 2, 3]
上面代碼表示,可以從數(shù)組中提取值会涎,按照對應位置裹匙,對變量賦值
解構賦值的規(guī)則是,只要等號右邊的值不是對象或數(shù)組末秃,就先將其轉為對象概页。由于
undefined
和null
無法轉為對象,所以對它們進行解構賦值练慕,都會報錯
let { prop: x } = undefined // TypeError
let { prop: y } = null // TypeError
4.1 數(shù)組的解構賦值
const arr = [1, 2, 3]
const [a, b, c] = arr
console.log(a, b, c) // 1, 2, 3
4.2 對象的解構賦值
let { foo1, foo2 } = { foo1: 'a', foo2: 'b' }
// foo1 => 'a' foo2 => 'b'
對象字面量的寫法:
let name = 'dahuang'
let color = 'yellow'
const dog = {name, color}
console.log(dog)
4.3 字符串的解構賦值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
4.4 數(shù)值和布爾值的解構賦值
解構賦值時惰匙,如果等號右邊是數(shù)值和布爾值,則會先轉為對象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
上面代碼中铃将,數(shù)值和布爾值的包裝對象都有
toString
屬性项鬼,因此變量s
都能取到值
4.5 函數(shù)參數(shù)的解構賦值
function add([x, y]){
return x + y
}
add([1, 2]) // 3
函數(shù)
add
的參數(shù)表面上是一個數(shù)組,但在傳入?yún)?shù)的那一刻劲阎,數(shù)組參數(shù)就被解構成變量x
和y
我們用Babel在線轉換工具把上述
ES6
代碼轉化為ES5
代碼看看绘盟,實際上就是講作為參數(shù)的數(shù)組分別結構成了x
和y
再返回他們的和
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
function add(_ref) {
var _ref2 = _slicedToArray(_ref, 2),
x = _ref2[0],
y = _ref2[1];
return x + y;
}
add([1, 2]); // 3
4.6 其他
當然對于解構賦值還有很多新玩法,例如可以添加默認值悯仙,這里阮一峰老師寫的很詳細奥此,請移步ES6標準入門
5 for...of
for...of
語句創(chuàng)建一個循環(huán)來迭代可迭代的對象跋核。在 ES6 中引入的for...of
循環(huán)样勃,以替代for...in
和forEach()
霞赫,并支持新的迭代協(xié)議空免。for...of
允許你遍歷 Arrays(數(shù)組), Strings(字符串), Maps(映射), Sets(集合)等可迭代的數(shù)據(jù)結構等
我們先來看看以前的方法
for 循環(huán)
let arr = [1, 2, 3, 4, 5, 6]
for (let i = 1; i < arr.length; i++) {
console.log(arr[i])
}
缺點:需要跟蹤計時器和退出條件
雖然 for
循環(huán)在循環(huán)數(shù)組時的確具有優(yōu)勢碎乃,但是某些數(shù)據(jù)結構不是數(shù)組杨耙,因此并非始終適合使用 loop 循環(huán)
for...in循環(huán)
let arr = [1, 2, 3, 4, 5, 6]
for (const index in arr) {
console.log(arr[index])
}
缺點: for...in
循環(huán)循環(huán)訪問所有可枚舉的屬性晋辆,意味著如果向數(shù)組的原型中添加任何其他屬性或者方法穿稳,這些屬性或方法也會出現(xiàn)在循環(huán)中茴她,這就無意間浪費了資源
forEach()循環(huán)
數(shù)組方法寻拂,只用于數(shù)組中,局限性大
for...of循環(huán)
const arrs = [1, 2, 3, 4, 5, 6]
for (const arr of arrs) {
console.log(arr)
}
// 可忽略索引
而且可以隨時退出或者停止for...of循環(huán)
const arrs = [1, 2, 3, 4, 5, 6]
for (const arr of arrs) {
if (arr % 2 === 0) {
continue
}
console.log(arr)
}
且不用擔心向對象中添加新的屬性丈牢。for...of 循環(huán)將只循環(huán)訪問對象中的值
6 展開運算符
ES6
中提供了展開運算符為...
const dogs = ['dahuang', 'xiaohei', 'xiaobai']
console.log(...dogs) // dahuang xiaohei xiaobai
6.1 數(shù)組拼合
const dogs = ['dahuang', 'xiaohei', 'xiaobai']
const peoples = ['xiaoming', 'zhangsan', 'zhaosi', 'wangwu']
const animals = [...dogs, ...peoples]
console.log(animals)
// ['dahuang', 'xiaohei', 'xiaobai', 'xiaoming', 'zhangsan', 'zhaosi', 'wangwu']
這實際上已經(jīng)完成了以前拼合數(shù)組使用的concat()
的功能
6.2 剩余參數(shù)
使用展開運算符將數(shù)組展開為多個元素, 使用剩余參數(shù)可以將多個元素綁定到一個數(shù)組中
- 將變量賦數(shù)組值
const goods = [20, 200, 'pen', 'book', 'ruler']
const [price, totalCount, ...studyGoods] = goods
console.log(price, totalCount, studyGoods)
// 前兩個參數(shù)對應前兩個祭钉,后面的作為數(shù)組傳入 studyGoods
- 可變剩余參數(shù)作為函數(shù)形參使用
function add (...numbers) {
let sum = 0
for (const number of numbers) {
sum += number
}
return sum
}
6.3 ES6 箭頭函數(shù)
箭頭函數(shù)是
ES6
中的一大亮點 ,下面看簡單的ES5
中的函數(shù) 和ES6
中的箭頭函數(shù)
ES5
中的函數(shù)
var fn = function () { console.log('我是es5') }
ES6
中的箭頭函數(shù)
const fn = () => { console.log('我是es6') }
// 等價于
const fn = () => console.log('我是es6')
就是講
ES5
中的function()
去掉己沛,變成() =>
慌核,且當函數(shù)體只有一句程序的時候,大括號也能省略
比較ES5中的函數(shù)和箭頭函數(shù):
- 前者可以使函數(shù)聲明或者函數(shù)表達式申尼,但是后者只能是函數(shù)表達式垮卓,因此只在表達式有效的時候才能使用
- 什么是表達式有效時?
- 存儲在變量中
- 當做參數(shù)傳遞給函數(shù)
- 存儲在對象屬性中
6.4 存儲在變量中的時候
其實上面的例子也說明了這點师幕,下面再舉兩個簡單的例子
const fn = numbers => `The pen are ${ numbers }`
// 調用
fn(200) // The pen are 200
const people = (name, age) => console.log(`${ name } is ${ age } years old`)
6.5 當做參數(shù)傳遞給函數(shù)的時候
將函數(shù)表達式當做參數(shù)傳遞給
map
函數(shù)粟按,一般就是用于需要回調的函數(shù)
const people = ['zhangsan', 'zhaosi', 'wangwu'].map(name => name.toUpperCase())
6.6 存儲在對象屬性中的時候
const people = {
name: 'zhangsan',
age: 10,
say: () => console.log('hello')
}
console.dir(people.say) // say() 方法
6.7 箭頭函數(shù)與this
對于普通函數(shù),
this
的值基于函數(shù)如何被調用, 對于箭頭函數(shù),this的值基于函數(shù)周圍的上下文, 換句話說,this的值和函數(shù)外面的this
的值是一樣的
6.7.1 普通情況下的this
-
new
對象,
const time = new Date() // 此時的this是Date()構造函數(shù)的實例對象
- 上下文
window.setTimeout() // 函數(shù)`setTimeout()`是對象`window`下的方法,此時this指向window
- 指定的對象
const arr = Array.prototype.slice.call(arr1)
const arr = Array.prototype.slice.apply(arr1)
// call 或者 apply 第一個參數(shù)設置 this 指向灭将,所以此時 this 指向 arr1
此外疼鸟,this 指向還有很多其他的講究,詳細見You-Dont-Know-JS
6.7.2 箭頭函數(shù)與this
我們首先來看一個例子
Array.prototype.init = function () {
console.log(this)
setTimeout(function () {
console.log(this)
}, 1000)
}
這時候兩次打印出來的
this
一樣嗎庙曙?執(zhí)行Array.prototype.init()
打印結果出來看一下:很顯然空镜,第一個打印出了
Array
構造函數(shù),第二個是Window
矾利,因為setTimeout()
是Window
的方法姑裂,所以會改變this
指向,那么使用箭頭函數(shù)看看
Array.prototype.init = function () {
console.log(this)
setTimeout( () => console.log(this), 1000)
}
Array.prototype.init()
這次就打印出了兩個
Array
男旗,this
指向沒有發(fā)生變化
6.7.3 應用場景
- 一些事件綁定之后需要操作原事件對象時防止
this
改變- 用到一些構造函數(shù)的方法的時候舶斧,防止該構造函數(shù)的
this
被改變- 等等......
7 Symbol
請移步我的另一篇博客ES6中的Symbol
8 class類
請移步我的另一篇博客ES6中的class關鍵字
9 Promise
請移步我的另一篇博客node-讀取文件方法封裝
10 Proxy
攔截代理,即在目標對象外層包裹一層攔截察皇,外接對對象的訪問都必須要先通過這層攔截茴厉,有點過濾的感覺,也有點像“門衛(wèi)”什荣,小區(qū)進門之前都要先過“門衛(wèi)”
10.1 語法
var proxy = new Proxy(target, handler)
10.2 參數(shù)
target
:對象類型矾缓,表示需要被攔截的對象handler
:對象類型,表示需要對這個對象target
要做的攔截操作
10.3 例子
var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
proxy.title // 35
如果
handler
沒有設置任何攔截稻爬,那就等同于直接通向原對象
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
11 Module
請移步我的另一篇博客ES6中Module語法與加載實現(xiàn)
12 參考文章
本文參考文章如下:
- 業(yè)界大佬阮一峰老師的ES6標準入門
- 一位道友的理解 JavaScript 中的 for…of 循環(huán)
- github上的You-Dont-Know-JS