從零開始學 Web 之 ES6(四)ES6基礎語法二
一、Promise
Promise是一個物件,代表了未來某個將要發生的事件(,這個事件通常是一個非同步操作)
有了Promise物件, 可以將非同步操作以同步的流程表達出來, 避免了層層巢狀的回撥函式(俗稱'回撥地獄')。
ES6的Promise是一個建構函式, 用來生成promise例項。
1、promise物件3個狀態
pending
: 初始化狀態fullfilled
: 成功狀態rejected
: 失敗狀態
2、使用方法
1、建立一個promise例項物件,引數是一個匿名函式,這個匿名函式有兩個引數,resolve和reject,
2、每一個引數都是一個回撥函式。然後,函式體中一般執行的是非同步操作,比如發起Ajax請求,或者開啟定時器等。
3、非同步操作成功時,呼叫resolve回撥函式,非同步操作失敗時,呼叫reject回撥函式。
4、在初始化Promise例項物件的時候,Promise的狀態為pending;在呼叫resolve回撥函式的時候,Promise的狀態為fullfilled,表示成功狀態;在呼叫reject回撥函式的時候,Promise的狀態為rejected,表示失敗狀態;
5、 Promise的例項物件有一個方法then,引數為兩個匿名函式,第一個匿名函式處理Promise的狀態為fullfilled的情況;第二個匿名函式處理Promise的狀態為rejected的情況;
6、上面說到,在非同步操作成功或者失敗的時候,會呼叫resolve和reject函式,在這兩個回撥函式中可以傳入引數,這個引數可以直接帶入到then中兩個匿名函式的引數中使用。比如獲取到ajax的資料,可以將獲取的數作為引數傳入resolve的引數中,然後會自動將這個引數傳入then的第一個匿名函式中,reject也一樣。
用圖示的方法表示:
示例:
let promise = new Promise((resolve, reject) => { console.log(111); // 執行非同步操作 setTimeout(() => { console.log(222); // 執行非同步操作成功,此時修改promise的狀態fullfilled resolve("success!"); // 執行非同步操作成功,此時修改promise的狀態rejected reject("failed!"); }, 2000); }); promise.then((data) => { // promise的狀態fullfilled的操作 console.log("成功", data); }, () => { // promise的狀態rejected的操作 console.log("失敗", data); });
注意:當執行到resolve("success!");修改promise的狀態fullfilled的時候,後面的reject("failed!");不會執行。也就不會列印console.log("失敗");的語句。
promise案例:獲取新聞內容和評論內容
// 定義一個請求news的方法
function getNews(url) {
//建立一個promise物件
let promise = new Promise((resolve, reject) => {
//初始化promise狀態為pending
//啟動非同步任務,發起Ajax請求
//1.建立一個 XMLHttpRequest 型別的物件
let request = new XMLHttpRequest();
// 4. 指定 xhr 狀態變化事件處理函式
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
let news = request.response;
resolve(news);
} else {
reject('請求失敗了...');
}
}
};
request.responseType = 'json'; //設定返回的資料型別
// 2. 開啟與一個網址之間的連線
request.open("GET", url); //規定請求的方法,建立連結
// 3. 通過連結傳送一次請求
request.send(); //傳送
})
// 只有將promise返回,才可以呼叫then方法
return promise;
};
// 呼叫getNews,獲取新聞內容,其中一個位元組為評論內容的地址
getNews('http://localhost:3000/news?id=2')
.then((news) => {
// 獲取到新聞內容
console.log(news);
// document.write(JSON.stringify(news));
// 獲取新聞內容中的評論地址
console.log('http://localhost:3000' + news.commentsUrl);
// 遞迴獲取新聞評論內容,並且返回promise物件,以便鏈式then方法。
return getNews('http://localhost:3000' + news.commentsUrl);
}, (error) => {
alert(error);
})
.then((comments) => { // then方法可以鏈式程式設計
console.log(comments);
// 把新聞的評論部分已json的格式打印出來顯示
document.write('<br><br><br><br><br>' + JSON.stringify(comments));
}, (error) => {
alert(error);
});
二、Symbol
ES5 的物件屬性名都是字串,這容易造成屬性名的衝突。比如,你使用了一個他人提供的物件,但又想為這個物件新增新的方法(mixin 模式),新方法的名字就有可能與現有方法產生衝突。如果有一種機制,保證每個屬性的名字都是獨一無二的就好了,這樣就從根本上防止屬性名的衝突。這就是 ES6 引入Symbol的原因。
1、Symbol屬性對應的值是唯一的,解決命名衝突問題
Symbol 是一種新的資料型別,跟 String,Number,Object,Boolean,null,undefined 並列。
Symbol 值通過Symbol
函式生成。這就是說,物件的屬性名現在可以有兩種型別,一種是原來就有的字串,另一種就是新增的 Symbol 型別。凡是屬性名屬於 Symbol 型別,就都是獨一無二的,可以保證不會與其他屬性名產生衝突。
let s = Symbol();
typeof s; // symbol
上面程式碼中,變數s
就是一個獨一無二的值。typeof
運算子的結果,表明變數s
是 Symbol 資料型別,而不是字串之類的其他型別。
注意,
Symbol
函式前不能使用new
命令,否則會報錯。這是因為生成的 Symbol 是一個原始型別的值,不是物件。也就是說,由於 Symbol 值不是物件,所以不能新增屬性。基本上,它是一種類似於字串的資料型別。
Symbol
函式可以接受一個字串作為引數,表示對 Symbol 例項的描述,主要是為了在控制檯顯示,或者轉為字串時,比較容易區分。
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
上面程式碼中,s1
和s2
是兩個 Symbol 值。如果不加引數,它們在控制檯的輸出都是Symbol()
,不利於區分。有了引數以後,就等於為它們加上了描述,輸出的時候就能夠分清,到底是哪一個值。
2、Symbol值不能與其他資料進行計算,包括同字串拼串
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
3、作為屬性名的 Symbol
由於每一個 Symbol 值都是不相等的,這意味著 Symbol 值可以作為識別符號,用於物件的屬性名,就能保證不會出現同名的屬性。這對於一個物件由多個模組構成的情況非常有用,能防止某一個鍵被不小心改寫或覆蓋。
let mySymbol = Symbol();
// 第一種寫法
let a = {};
a[mySymbol] = 'Hello!';
// 第二種寫法
let a = {
[mySymbol]: 'Hello!'
};
// 第三種寫法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上寫法都得到同樣結果
a[mySymbol] // "Hello!"
注意,Symbol 值作為物件屬性名時,不能用點運算子。
a.mySymbol = 'Hello!';
4、for in, for of遍歷時不會遍歷symbol屬性
let obj = {
username: 'Daotin',
age: 18
};
obj[symbol] = 'hello';
obj[symbol] = 'symbol';
console.log(obj);
for (let i in obj) {
console.log(i);
}
5、內建的 Symbol 值
除了定義自己使用的 Symbol 值以外,ES6 還提供了 11 個內建的 Symbol 值,指向語言內部使用的方法。
6、Symbol.hasInstance
物件的Symbol.hasInstance
屬性,指向一個內部方法。當其他物件使用instanceof
運算子,判斷是否為該物件的例項時,會呼叫這個方法。比如,foo instanceof Foo
在語言內部,實際呼叫的是Foo[Symbol.hasInstance](foo)
。
7、Symbol.iterator
物件的Symbol.iterator
屬性,指向該物件的預設遍歷器方法。
三、Iterator
Iterator 是迭代器(遍歷器)的意思。
JavaScript 原有的表示“集合”的資料結構,主要是陣列(Array
)和物件(Object
),ES6 又添加了Map
和Set
。這樣就有了四種資料集合,使用者還可以組合使用它們,定義自己的資料結構,比如陣列的成員是Map
,Map
的成員是物件。這樣就需要一種統一的介面機制,來處理所有不同的資料結構。
遍歷器(Iterator)就是這樣一種機制。它是一種介面,為各種不同的資料結構提供統一的訪問機制。任何資料結構只要部署 Iterator 介面,就可以完成遍歷操作(即依次處理該資料結構的所有成員)。
Iterator 的作用:
- 為各種資料結構,提供一個統一的、簡便的訪問介面
- 使得資料結構的成員能夠按某種次序排列
- ES6 創造了一種新的遍歷命令
for...of
迴圈,Iterator 介面主要供for...of
消費。
Iterator 的遍歷過程:
(1)建立一個指標物件,指向當前資料結構的起始位置。也就是說,遍歷器物件本質上,就是一個指標物件。
(2)第一次呼叫指標物件的next方法,可以將指標指向資料結構的第一個成員。
(3)第二次呼叫指標物件的next方法,指標就指向資料結構的第二個成員。
(4)不斷呼叫指標物件的next方法,直到它指向資料結構的結束位置。
每一次呼叫next方法,都會返回資料結構的當前成員的資訊。具體來說,就是返回一個包含value和done兩個屬性的物件。其中,value屬性是當前成員的值,done屬性是一個布林值,表示遍歷是否結束。
下面是一個模擬next
方法返回值的例子。
var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}
對於遍歷器物件來說,done: false
和value: undefined
屬性都是可以省略的,因此上面的makeIterator
函式可以簡寫成下面的形式。
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++]} :
{done: true};
}
};
}
1、預設 Iterator 介面
ES6 規定,預設的 Iterator 介面部署在資料結構的Symbol.iterator
屬性,或者說,一個數據結構只要具有Symbol.iterator
屬性,就可以認為是“可遍歷的”(iterable)。
Symbol.iterator
屬性本身是一個函式,就是當前資料結構預設的遍歷器生成函式。執行這個函式,就會返回一個遍歷器。至於屬性名Symbol.iterator
,它是一個表示式,返回Symbol
物件的iterator
屬性,這是一個預定義好的、型別為 Symbol 的特殊值,所以要放在方括號內.
const obj = {
[Symbol.iterator] : function () {
return {
next: function () {
return {
value: 1,
done: true
};
}
};
}
};
上面程式碼中,物件obj
是可遍歷的(iterable),因為具有Symbol.iterator
屬性。執行這個屬性,會返回一個遍歷器物件。該物件的根本特徵就是具有next
方法。每次呼叫next
方法,都會返回一個代表當前成員的資訊物件,具有value
和done
兩個屬性。
ES6 的有些資料結構原生具備 Iterator 介面(比如陣列),即不用任何處理,就可以被for...of
迴圈遍歷。原因在於,這些資料結構原生部署了Symbol.iterator
屬性(詳見下文),另外一些資料結構沒有(比如物件)。凡是部署了Symbol.iterator
屬性的資料結構,就稱為部署了遍歷器介面。呼叫這個介面,就會返回一個遍歷器物件。
原生具備 Iterator 介面的資料結構如下。
- Array
- Map
- Set
- String
- TypedArray
- 函式的 arguments 物件
- NodeList 物件
下面的例子是陣列的Symbol.iterator
屬性。
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
上面程式碼中,變數arr
是一個數組,原生就具有遍歷器介面,部署在arr
的Symbol.iterator
屬性上面。所以,呼叫這個屬性,就得到遍歷器物件。
對於原生部署 Iterator 介面的資料結構,不用自己寫遍歷器生成函式,for...of
迴圈會自動遍歷它們。除此之外,其他資料結構(主要是物件)的 Iterator 介面,都需要自己在Symbol.iterator
屬性上面部署,這樣才會被for...of
迴圈遍歷。
一個物件如果要具備可被for...of
迴圈呼叫的 Iterator 介面,就必須在Symbol.iterator
的屬性上部署遍歷器生成方法(原型鏈上的物件具有該方法也可)。
2、呼叫 Iterator 介面的場合
- 使用解構賦值以及...三點運算子時會呼叫iterator介面
let arr1 = [1, 2, 3, 4, 5];
let [value1, ...arr2] = arr1;
for..of..遍歷
// 原生測試 陣列
let arr3 = [1, 2, 'kobe', true];
for (let i of arr3) {
console.log(i);
}
// 字串 string
let str = 'abcdefg';
for (let item of str) {
console.log(item);
}
相關推薦
從零開始學 Web 之 DOM(四)節點
def clas scrip while p標簽 設置 ner 操作 text 大家好,這裏是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關註。在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相
從零開始學 Web 之 BOM(四)client系列
一、client 系列 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style
從零開始學 Web 之 JavaScript(四)陣列
大家好,這裡是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關注。在這裡我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的專案。現在就讓我們一起進入 Web 前端學習的冒險之旅吧! 一、陣列 1、陣列
從零開始學 Web 之 Ajax(四)介面文件,驗證使用者名稱唯一性案例
>大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... > > - github:https://github.com/Daotin/Web > - 微信公眾號:[Web前端之巔](https://github.com/Daotin/pi
從零開始學 Web 之 HTML5(四)拖拽介面,Web儲存,自定義播放器
>大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... > > - github:https://github.com/Daotin/Web > - 微信公眾號:[Web前端之巔](https://github.com/Daotin/pi
從零開始學 Web 之 CSS(四)CSS初始化、定位、overflow、標籤規範
大家好,這裡是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關注。在這裡我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的專案。現在就讓我們一起進入 Web 前端學習的冒險之旅吧! 一、CSS初始化
從零開始學 Web 之 jQuery(四)元素的建立新增與刪除,自定義屬性
一、元素的建立新增和刪除 1、方式一:以物件的方式建立元素 append,appendTo :在被選元素所有子元素的結尾插入內容(增加子元素)。 prepend,prependTo:在被選元素所有子元素的開頭插入元素(增加子元素)。 before:在當前被選元素之後插入內容(相當於增加兄弟元素)。 af
從零開始學 Web 之 CSS3(四)邊框圖片,過渡
一、邊框圖片 邊框圖片:就是給邊框加圖片背景。 我們之前加的邊框都是純顏色的邊框,那麼我們怎麼給邊框加圖片呢? 原理:把一張圖片分成九宮格的形式,然後一一對應到需要新增邊框的元素上。 並且,新增邊框圖片是以背景的方式新增的,所以會有可能文字覆蓋在邊框的情況,後面也會介紹處理方法。 語法: /* bord
從零開始學 Web 之 DOM(一)DOM的概念,對標簽操作
關註 1.5 pan 什麽 tin p標簽 nod text == 大家好,這裏是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關註。在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,
從零開始學 Web 之 BOM(三)offset,scroll,變速動畫函數
樣式 清理 java mar dde sof mov har width 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:
從零開始學 Web 之 jQuery(六)為元素綁定多個相同事件,解綁事件
png 好用 添加 方式 執行 存在 區別 也會 地址 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:http://ww
從零開始學 Web 之 jQuery(七)事件冒泡,事件參數對象,鏈式編程原理
eval uri turn 定位 return 也會 否則 ont sele 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客
從零開始學 Web 之 Ajax(三)Ajax 概述,快速上手
lan 技術分享 php 概述 由於 val asc logs 更新 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:ht
從零開始學 Web 之 Ajax(五)同步異步請求,數據格式
遊記 document 空閑 name center 20px 實現 resp 也會 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之
從零開始學 Web 之 Ajax(六)jQuery中的Ajax
var 技術分享 else parse cnblogs 我會 clas alt jquer 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web
從零開始學 Web 之 CSS3(一)CSS3概述,選擇器
https 兼容問題 3.1 線性 web前端 不同 錨點 splay lock 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔
從零開始學 Web 之 CSS(一)選擇器
大家好,這裡是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關注。在這裡我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的專案。現在就讓我們一起進入 W
從零開始學 Web 之 CSS3(五)transform
transform transform 字面上就是變形,改變的意思。在CSS3中transform主要包括以下幾種:移動 translate,縮放scale,旋轉rotate,翻轉skew,改變旋轉軸心等。 1、元素的移動:translate 作用:使用transform實現元素的移動 語法: /*使用t
從零開始學 Web 之 jQuery(三)元素操作,鏈式程式設計,動畫方法
一、使用css操作元素樣式 1、常規寫法 $("#dv").css("width", "200px"); $("#dv").css("height", "100px"); $("#dv").css("background", "red"); 2、鏈式寫法 $("#dv").css("width", "20
從零開始學 Web 之 DOM(六)為元素繫結與解綁事件
大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... +------------------------------------------------------------ github:https://github.com/Daotin/Web 微信公眾號:Web前端之