久久精品中文字幕av,av.涩涩涩涩涩涩涩涩,亚洲国产日韩欧美精品成人久久久,成人福利电影免费在线观看,日产国产原创av,日韩av午夜激情,bt天堂中文字幕,超级碰人妻在线视频,欧美老熟妇久久一区二区

企業(yè)??AI智能體構(gòu)建引擎,智能編排和調(diào)試,一鍵部署,支持知識庫和私有化部署方案 廣告
<h2 id="9.1">Promise</h2> Promise是JavaScript異步操作解決方案。介紹Promise之前,先對異步操作做一個詳細介紹。 ## JavaScript的異步執(zhí)行 ### 概述 Javascript語言的執(zhí)行環(huán)境是"單線程"(single thread)。所謂"單線程",就是指一次只能完成一件任務(wù)。如果有多個任務(wù),就必須排隊,前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù)。 這種模式的好處是實現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純;壞處是只要有一個任務(wù)耗時很長,后面的任務(wù)都必須排隊等著,會拖延整個程序的執(zhí)行。常見的瀏覽器無響應(yīng)(假死),往往就是因為某一段Javascript代碼長時間運行(比如死循環(huán)),導(dǎo)致整個頁面卡在這個地方,其他任務(wù)無法執(zhí)行。 JavaScript語言本身并不慢,慢的是讀寫外部數(shù)據(jù),比如等待Ajax請求返回結(jié)果。這個時候,如果對方服務(wù)器遲遲沒有響應(yīng),或者網(wǎng)絡(luò)不通暢,就會導(dǎo)致腳本的長時間停滯。 為了解決這個問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。"同步模式"就是傳統(tǒng)做法,后一個任務(wù)等待前一個任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的。這往往用于一些簡單的、快速的、不涉及讀寫的操作。 "異步模式"則完全不同,每一個任務(wù)分成兩段,第一段代碼包含對外部數(shù)據(jù)的請求,第二段代碼被寫成一個回調(diào)函數(shù),包含了對外部數(shù)據(jù)的處理。第一段代碼執(zhí)行完,不是立刻執(zhí)行第二段代碼,而是將程序的執(zhí)行權(quán)交給第二個任務(wù)。等到外部數(shù)據(jù)返回了,再由系統(tǒng)通知執(zhí)行第二段代碼。所以,程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。 以下總結(jié)了"異步模式"編程的幾種方法,理解它們可以讓你寫出結(jié)構(gòu)更合理、性能更出色、維護更方便的JavaScript程序。 ### 回調(diào)函數(shù) 回調(diào)函數(shù)是異步編程最基本的方法。 假定有兩個函數(shù)f1和f2,后者等待前者的執(zhí)行結(jié)果。 ```javascript f1(); f2(); ``` 如果`f1`是一個很耗時的任務(wù),可以考慮改寫`f1`,把`f2`寫成`f1`的回調(diào)函數(shù)。 ```javascript function f1(callback){ setTimeout(function () { // f1的任務(wù)代碼 callback(); }, 1000); } ``` 執(zhí)行代碼就變成下面這樣: ```javascript f1(f2); ``` 采用這種方式,我們把同步操作變成了異步操作,f1不會堵塞程序運行,相當(dāng)于先執(zhí)行程序的主要邏輯,將耗時的操作推遲執(zhí)行。 回調(diào)函數(shù)的優(yōu)點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護,各個部分之間高度[耦合](http://en.wikipedia.org/wiki/Coupling_(computer_programming))(Coupling),使得程序結(jié)構(gòu)混亂、流程難以追蹤(尤其是回調(diào)函數(shù)嵌套的情況),而且每個任務(wù)只能指定一個回調(diào)函數(shù)。 ### 事件監(jiān)聽 另一種思路是采用事件驅(qū)動模式。任務(wù)的執(zhí)行不取決于代碼的順序,而取決于某個事件是否發(fā)生。 還是以f1和f2為例。首先,為f1綁定一個事件(這里采用的jQuery的[寫法](http://api.jquery.com/on/))。 ```javascript f1.on('done', f2); ``` 上面這行代碼的意思是,當(dāng)f1發(fā)生done事件,就執(zhí)行f2。然后,對f1進行改寫: ```javascript function f1(){ setTimeout(function () { // f1的任務(wù)代碼 f1.trigger('done'); }, 1000); } ``` 上面代碼中,`f1.trigger('done')`表示,執(zhí)行完成后,立即觸發(fā)`done`事件,從而開始執(zhí)行`f2`。 這種方法的優(yōu)點是比較容易理解,可以綁定多個事件,每個事件可以指定多個回調(diào)函數(shù),而且可以"[去耦合](http://en.wikipedia.org/wiki/Decoupling)"(Decoupling),有利于實現(xiàn)模塊化。缺點是整個程序都要變成事件驅(qū)動型,運行流程會變得很不清晰。 ### 發(fā)布/訂閱 "事件"完全可以理解成"信號",如果存在一個"信號中心",某個任務(wù)執(zhí)行完成,就向信號中心"發(fā)布"(publish)一個信號,其他任務(wù)可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執(zhí)行。這就叫做"[發(fā)布/訂閱模式](http://en.wikipedia.org/wiki/Publish-subscribe_pattern)"(publish-subscribe pattern),又稱"[觀察者模式](http://en.wikipedia.org/wiki/Observer_pattern)"(observer pattern)。 這個模式有多種[實現(xiàn)](http://msdn.microsoft.com/en-us/magazine/hh201955.aspx),下面采用的是Ben Alman的[Tiny Pub/Sub](https://gist.github.com/661855),這是jQuery的一個插件。 首先,f2向"信號中心"jQuery訂閱"done"信號。 ```javascript jQuery.subscribe("done", f2); ``` 然后,f1進行如下改寫: ```javascript function f1(){ setTimeout(function () { // f1的任務(wù)代碼 jQuery.publish("done"); }, 1000); } ``` jQuery.publish("done")的意思是,f1執(zhí)行完成后,向"信號中心"jQuery發(fā)布"done"信號,從而引發(fā)f2的執(zhí)行。 f2完成執(zhí)行后,也可以取消訂閱(unsubscribe)。 ```javascript jQuery.unsubscribe("done", f2); ``` 這種方法的性質(zhì)與"事件監(jiān)聽"類似,但是明顯優(yōu)于后者。因為我們可以通過查看"消息中心",了解存在多少信號、每個信號有多少訂閱者,從而監(jiān)控程序的運行。 ## 異步操作的流程控制 如果有多個異步操作,就存在一個流程控制的問題:確定操作執(zhí)行的順序,以后如何保證遵守這種順序。 ```javascript function async(arg, callback) { console.log('參數(shù)為 ' + arg +' , 1秒后返回結(jié)果'); setTimeout(function() { callback(arg * 2); }, 1000); } ``` 上面代碼的async函數(shù)是一個異步任務(wù),非常耗時,每次執(zhí)行需要1秒才能完成,然后再調(diào)用回調(diào)函數(shù)。 如果有6個這樣的異步任務(wù),需要全部完成后,才能執(zhí)行下一步的final函數(shù)。 ```javascript function final(value) { console.log('完成: ', value); } ``` 請問應(yīng)該如何安排操作流程? ```javascript async(1, function(value){ async(value, function(value){ async(value, function(value){ async(value, function(value){ async(value, function(value){ async(value, final); }); }); }); }); }); ``` 上面代碼采用6個回調(diào)函數(shù)的嵌套,不僅寫起來麻煩,容易出錯,而且難以維護。 ### 串行執(zhí)行 我們可以編寫一個流程控制函數(shù),讓它來控制異步任務(wù),一個任務(wù)完成以后,再執(zhí)行另一個。這就叫串行執(zhí)行。 ```javascript var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function series(item) { if(item) { async( item, function(result) { results.push(result); return series(items.shift()); }); } else { return final(results); } } series(items.shift()); ``` 上面代碼中,函數(shù)series就是串行函數(shù),它會依次執(zhí)行異步任務(wù),所有任務(wù)都完成后,才會執(zhí)行final函數(shù)。items數(shù)組保存每一個異步任務(wù)的參數(shù),results數(shù)組保存每一個異步任務(wù)的運行結(jié)果。 ### 并行執(zhí)行 流程控制函數(shù)也可以是并行執(zhí)行,即所有異步任務(wù)同時執(zhí)行,等到全部完成以后,才執(zhí)行final函數(shù)。 ```javascript var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; items.forEach(function(item) { async(item, function(result){ results.push(result); if(results.length == items.length) { final(results); } }) }); ``` 上面代碼中,forEach方法會同時發(fā)起6個異步任務(wù),等到它們?nèi)客瓿梢院?,才會?zhí)行final函數(shù)。 并行執(zhí)行的好處是效率較高,比起串行執(zhí)行一次只能執(zhí)行一個任務(wù),較為節(jié)約時間。但是問題在于如果并行的任務(wù)較多,很容易耗盡系統(tǒng)資源,拖慢運行速度。因此有了第三種流程控制方式。 ### 并行與串行的結(jié)合 所謂并行與串行的結(jié)合,就是設(shè)置一個門檻,每次最多只能并行執(zhí)行n個異步任務(wù)。這樣就避免了過分占用系統(tǒng)資源。 ```javascript var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; var running = 0; var limit = 2; function launcher() { while(running < limit && items.length > 0) { var item = items.shift(); async(item, function(result) { results.push(result); running--; if(items.length > 0) { launcher(); } else if(running == 0) { final(); } }); running++; } } launcher(); ``` 上面代碼中,最多只能同時運行兩個異步任務(wù)。變量running記錄當(dāng)前正在運行的任務(wù)數(shù),只要低于門檻值,就再啟動一個新的任務(wù),如果等于0,就表示所有任務(wù)都執(zhí)行完了,這時就執(zhí)行final函數(shù)。 ## Promise對象 ### 簡介 Promise對象是CommonJS工作組提出的一種規(guī)范,目的是為異步操作提供[統(tǒng)一接口](http://wiki.commonjs.org/wiki/Promises/A)。 那么,什么是Promises? 首先,它是一個對象,也就是說與其他JavaScript對象的用法,沒有什么兩樣;其次,它起到代理作用(proxy),充當(dāng)異步操作與回調(diào)函數(shù)之間的中介。它使得異步操作具備同步操作的接口,使得程序具備正常的同步運行的流程,回調(diào)函數(shù)不必再一層層嵌套。 簡單說,它的思想是,每一個異步任務(wù)立刻返回一個Promise對象,由于是立刻返回,所以可以采用同步操作的流程。這個Promises對象有一個then方法,允許指定回調(diào)函數(shù),在異步任務(wù)完成后調(diào)用。 比如,異步操作`f1`返回一個Promise對象,它的回調(diào)函數(shù)`f2`寫法如下。 ```javascript (new Promise(f1)).then(f2); ``` 這種寫法對于多層嵌套的回調(diào)函數(shù)尤其方便。 ```javascript // 傳統(tǒng)寫法 step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // ... }); }); }); }); // Promises的寫法 (new Promise(step1)) .then(step2) .then(step3) .then(step4); ``` 從上面代碼可以看到,采用Promises接口以后,程序流程變得非常清楚,十分易讀。 注意,為了便于理解,上面代碼的Promise對象的生成格式,做了簡化,真正的語法請參照下文。 總的來說,傳統(tǒng)的回調(diào)函數(shù)寫法使得代碼混成一團,變得橫向發(fā)展而不是向下發(fā)展。Promises規(guī)范就是為了解決這個問題而提出的,目標(biāo)是使用正常的程序流程(同步),來處理異步操作。它先返回一個Promise對象,后面的操作以同步的方式,寄存在這個對象上面。等到異步操作有了結(jié)果,再執(zhí)行前期寄放在它上面的其他操作。 Promises原本只是社區(qū)提出的一個構(gòu)想,一些外部函數(shù)庫率先實現(xiàn)了這個功能。ECMAScript 6將其寫入語言標(biāo)準(zhǔn),因此目前JavaScript語言原生支持Promise對象。 ### Promise接口 前面說過,Promise接口的基本思想是,異步任務(wù)返回一個Promise對象。 Promise對象只有三種狀態(tài)。 - 異步操作“未完成”(pending) - 異步操作“已完成”(resolved,又稱fulfilled) - 異步操作“失敗”(rejected) 這三種的狀態(tài)的變化途徑只有兩種。 - 異步操作從“未完成”到“已完成” - 異步操作從“未完成”到“失敗”。 這種變化只能發(fā)生一次,一旦當(dāng)前狀態(tài)變?yōu)椤耙淹瓿伞被颉笆 ?,就意味著不會再有新的狀態(tài)變化了。因此,Promise對象的最終結(jié)果只有兩種。 - 異步操作成功,Promise對象傳回一個值,狀態(tài)變?yōu)閌resolved`。 - 異步操作失敗,Promise對象拋出一個錯誤,狀態(tài)變?yōu)閌rejected`。 Promise對象使用`then`方法添加回調(diào)函數(shù)。`then`方法可以接受兩個回調(diào)函數(shù),第一個是異步操作成功時(變?yōu)閌resolved`狀態(tài))時的回調(diào)函數(shù),第二個是異步操作失?。ㄗ?yōu)閌rejected`)時的回調(diào)函數(shù)(可以省略)。一旦狀態(tài)改變,就調(diào)用相應(yīng)的回調(diào)函數(shù)。 ```javascript // po是一個Promise對象 po.then( console.log, console.error ); ``` 上面代碼中,Promise對象`po`使用`then`方法綁定兩個回調(diào)函數(shù):操作成功時的回調(diào)函數(shù)`console.log`,操作失敗時的回調(diào)函數(shù)`console.error`(可以省略)。這兩個函數(shù)都接受異步操作傳回的值作為參數(shù)。 `then`方法可以鏈?zhǔn)绞褂谩? ```javascript po .then(step1) .then(step2) .then(step3) .then( console.log, console.error ); ``` 上面代碼中,`po`的狀態(tài)一旦變?yōu)閌resolved`,就依次調(diào)用后面每一個`then`指定的回調(diào)函數(shù),每一步都必須等到前一步完成,才會執(zhí)行。最后一個`then`方法的回調(diào)函數(shù)`console.log`和`console.error`,用法上有一點重要的區(qū)別。`console.log`只顯示回調(diào)函數(shù)`step3`的返回值,而`console.error`可以顯示`step1`、`step2`、`step3`之中任意一個發(fā)生的錯誤。也就是說,假定`step1`操作失敗,拋出一個錯誤,這時`step2`和`step3`都不會再執(zhí)行了(因為它們是操作成功的回調(diào)函數(shù),而不是操作失敗的回調(diào)函數(shù))。Promises對象開始尋找,接下來第一個操作失敗時的回調(diào)函數(shù),在上面代碼中是`console.error`。這就是說,Promises對象的錯誤有傳遞性。 從同步的角度看,上面的代碼大致等同于下面的形式。 ```javascript try { var v1 = step1(po); var v2 = step2(v1); var v3 = step3(v2); console.log(v3); } catch (error) { console.error(error); } ``` ### Promise對象的生成 ES6提供了原生的Promise構(gòu)造函數(shù),用來生成Promise實例。 下面代碼創(chuàng)造了一個Promise實例。 ```javascript var promise = new Promise(function(resolve, reject) { // 異步操作的代碼 if (/* 異步操作成功 */){ resolve(value); } else { reject(error); } }); ``` Promise構(gòu)造函數(shù)接受一個函數(shù)作為參數(shù),該函數(shù)的兩個參數(shù)分別是`resolve`和`reject`。它們是兩個函數(shù),由JavaScript引擎提供,不用自己部署。 `resolve`函數(shù)的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸腵Pending`變?yōu)閌Resolved`),在異步操作成功時調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去;`reject`函數(shù)的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤笆 保磸腵Pending`變?yōu)閌Rejected`),在異步操作失敗時調(diào)用,并將異步操作報出的錯誤,作為參數(shù)傳遞出去。 Promise實例生成以后,可以用`then`方法分別指定`Resolved`狀態(tài)和`Reject`狀態(tài)的回調(diào)函數(shù)。 ```javascript po.then(function(value) { // success }, function(value) { // failure }); ``` ### 用法辨析 Promise的用法,簡單說就是一句話:使用`then`方法添加回調(diào)函數(shù)。但是,不同的寫法有一些細微的差別,請看下面四種寫法,它們的差別在哪里? ```javascript // 寫法一 doSomething().then(function () { return doSomethingElse(); }); // 寫法二 doSomething().then(function () { doSomethingElse(); }); // 寫法三 doSomething().then(doSomethingElse()); // 寫法四 doSomething().then(doSomethingElse); ``` 為了便于講解,這四種寫法都再用`then`方法接一個回調(diào)函數(shù)`finalHandler`。寫法一的`finalHandler`回調(diào)函數(shù)的參數(shù),是`doSomethingElse`函數(shù)的運行結(jié)果。 ```javascript doSomething().then(function () { return doSomethingElse(); }).then(finalHandler); ``` 寫法二的`finalHandler`回調(diào)函數(shù)的參數(shù)是`undefined`。 ```javascript doSomething().then(function () { doSomethingElse(); return; }).then(finalHandler); ``` 寫法三的`finalHandler`回調(diào)函數(shù)的參數(shù),是`doSomethingElse`函數(shù)返回的回調(diào)函數(shù)的運行結(jié)果。 ```javascript doSomething().then(doSomethingElse()) .then(finalHandler); ``` 寫法四與寫法一只有一個差別,那就是`doSomethingElse`會接收到`doSomething()`返回的結(jié)果。 ```javascript doSomething().then(doSomethingElse) .then(finalHandler); ``` ## Promise的應(yīng)用 ### 加載圖片 我們可以把圖片的加載寫成一個`Promise`對象。 ```javascript var preloadImage = function (path) { return new Promise(function (resolve, reject) { var image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); }; ``` ### Ajax操作 Ajax操作是典型的異步操作,傳統(tǒng)上往往寫成下面這樣。 ```javascript function search(term, onload, onerror) { var xhr, results, url; url = 'http://example.com/search?q=' + term; xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onload = function (e) { if (this.status === 200) { results = JSON.parse(this.responseText); onload(results); } }; xhr.onerror = function (e) { onerror(e); }; xhr.send(); } search("Hello World", console.log, console.error); ``` 如果使用Promise對象,就可以寫成下面這樣。 ```javascript function search(term) { var url = 'http://example.com/search?q=' + term; var xhr = new XMLHttpRequest(); var result; var p = new Promise(function (resolve, reject) { xhr.open('GET', url, true); xhr.onload = function (e) { if (this.status === 200) { result = JSON.parse(this.responseText); resolve(result); } }; xhr.onerror = function (e) { reject(e); }; xhr.send(); }); return p; } search("Hello World").then(console.log, console.error); ``` 加載圖片的例子,也可以用Ajax操作完成。 ```javascript function imgLoad(url) { return new Promise(function(resolve, reject) { var request = new XMLHttpRequest(); request.open('GET', url); request.responseType = 'blob'; request.onload = function() { if (request.status === 200) { resolve(request.response); } else { reject(new Error('圖片加載失?。?#039; + request.statusText)); } }; request.onerror = function() { reject(new Error('發(fā)生網(wǎng)絡(luò)錯誤')); }; request.send(); }); } ``` ### 小結(jié) Promise對象的優(yōu)點在于,讓回調(diào)函數(shù)變成了規(guī)范的鏈?zhǔn)綄懛ǎ绦蛄鞒炭梢钥吹煤芮宄K囊徽捉涌?,可以實現(xiàn)許多強大的功能,比如為多個異步操作部署一個回調(diào)函數(shù)、為多個回調(diào)函數(shù)中拋出的錯誤統(tǒng)一指定處理方法等等。 而且,它還有一個前面三種方法都沒有的好處:如果一個任務(wù)已經(jīng)完成,再添加回調(diào)函數(shù),該回調(diào)函數(shù)會立即執(zhí)行。所以,你不用擔(dān)心是否錯過了某個事件或信號。這種方法的缺點就是,編寫和理解都相對比較難。 <h2 id="9.2">JavaScript與有限狀態(tài)機</h2> ## 概述 有限狀態(tài)機(Finite-state machine)是一個非常有用的模型,可以模擬世界上大部分事物。 簡單說,它有三個特征: - 狀態(tài)總數(shù)(state)是有限的。 - 任一時刻,只處在一種狀態(tài)之中。 - 某種條件下,會從一種狀態(tài)轉(zhuǎn)變(transition)到另一種狀態(tài)。 它對JavaScript的意義在于,很多對象可以寫成有限狀態(tài)機。 舉例來說,網(wǎng)頁上有一個菜單元素。鼠標(biāo)點擊,菜單顯示;鼠標(biāo)再次點擊,菜單隱藏。如果使用有限狀態(tài)機描述,就是這個菜單只有兩種狀態(tài)(顯示和隱藏),鼠標(biāo)會引發(fā)狀態(tài)轉(zhuǎn)變。 代碼可以寫成下面這樣: ```javascript var menu = {      // 當(dāng)前狀態(tài)   currentState: 'hide',      // 綁定事件   initialize: function() {     var self = this;     self.on("click", self.transition);   },      // 狀態(tài)轉(zhuǎn)換   transition: function(event){     switch(this.currentState) {       case "hide":         this.currentState = 'show';         doSomething();         break;       case "show":         this.currentState = 'hide';         doSomething();         break;       default:         console.log('Invalid State!');         break;     }   }    }; ``` 可以看到,有限狀態(tài)機的寫法,邏輯清晰,表達力強,有利于封裝事件。一個對象的狀態(tài)越多、發(fā)生的事件越多,就越適合采用有限狀態(tài)機的寫法。 另外,JavaScript語言是一種異步操作特別多的語言,常用的解決方法是指定回調(diào)函數(shù),但這樣會造成代碼結(jié)構(gòu)混亂、難以測試和除錯等問題。有限狀態(tài)機提供了更好的辦法:把異步操作與對象的狀態(tài)改變掛鉤,當(dāng)異步操作結(jié)束的時候,發(fā)生相應(yīng)的狀態(tài)改變,由此再觸發(fā)其他操作。這要比回調(diào)函數(shù)、事件監(jiān)聽、發(fā)布/訂閱等解決方案,在邏輯上更合理,更易于降低代碼的復(fù)雜度。 ## Javascript Finite State Machine函數(shù)庫 下面介紹一個有限狀態(tài)機的函數(shù)庫[Javascript Finite State Machine](https://github.com/jakesgordon/javascript-state-machine)。這個庫非常好懂,可以幫助我們加深理解,而且功能一點都不弱。 該庫提供一個全局對象StateMachine,使用該對象的create方法,可以生成有限狀態(tài)機的實例。 ```javascript var fsm = StateMachine.create(); ``` 生成的時候,需要提供一個參數(shù)對象,用來描述實例的性質(zhì)。比如,交通信號燈(紅綠燈)可以這樣描述: ```javascript var fsm = StateMachine.create({      initial: 'green',      events: [     { name: 'warn', from: 'green', to: 'yellow' },     { name: 'stop', from: 'yellow', to: 'red' },     { name: 'ready', from: 'red', to: 'yellow' },     { name: 'go', from: 'yellow', to: 'green' }   ]    }); ``` 交通信號燈的初始狀態(tài)(initial)為green,events屬性是觸發(fā)狀態(tài)改變的各種事件,比如warn事件使得green狀態(tài)變成yellow狀態(tài),stop事件使得yellow狀態(tài)變成red狀態(tài)等等。 生成實例以后,就可以隨時查詢當(dāng)前狀態(tài)。 - fsm.current :返回當(dāng)前狀態(tài)。 - fsm.is(s) :返回一個布爾值,表示狀態(tài)s是否為當(dāng)前狀態(tài)。 - fsm.can(e) :返回一個布爾值,表示事件e是否能在當(dāng)前狀態(tài)觸發(fā)。 - fsm.cannot(e) :返回一個布爾值,表示事件e是否不能在當(dāng)前狀態(tài)觸發(fā)。 Javascript Finite State Machine允許為每個事件指定兩個回調(diào)函數(shù),以warn事件為例: - onbefore**warn**:在warn事件發(fā)生之前觸發(fā)。 - onafter**warn**(可簡寫成onwarn) :在warn事件發(fā)生之后觸發(fā)。 同時,它也允許為每個狀態(tài)指定兩個回調(diào)函數(shù),以green狀態(tài)為例: - onleave**green** :在離開green狀態(tài)時觸發(fā)。 - onenter**green**(可簡寫成ongreen) :在進入green狀態(tài)時觸發(fā)。 假定warn事件使得狀態(tài)從green變?yōu)閥ellow,上面四類回調(diào)函數(shù)的發(fā)生順序如下:onbefore**warn** → onleave**green** → onenter**yellow** → onafter**warn**。 除了為每個事件和狀態(tài)單獨指定回調(diào)函數(shù),還可以為所有的事件和狀態(tài)指定通用的回調(diào)函數(shù)。 - onbeforeevent :任一事件發(fā)生之前觸發(fā)。 - onleavestate :離開任一狀態(tài)時觸發(fā)。 - onenterstate :進入任一狀態(tài)時觸發(fā)。 - onafterevent :任一事件結(jié)束后觸發(fā)。 如果事件的回調(diào)函數(shù)里面有異步操作(比如與服務(wù)器進行Ajax通信),這時我們可能希望等到異步操作結(jié)束,再發(fā)生狀態(tài)改變。這就要用到transition方法。 ```javascript fsm.onleavegreen = function(){   light.fadeOut('slow', function() {     fsm.transition();   });   return StateMachine.ASYNC; }; ``` 上面代碼的回調(diào)函數(shù)里面,有一個異步操作(light.fadeOut)。如果不希望狀態(tài)立即改變,就要讓回調(diào)函數(shù)返回StateMachine.ASYNC,表示狀態(tài)暫時不改變;等到異步操作結(jié)束,再調(diào)用transition方法,使得狀態(tài)發(fā)生改變。 Javascript Finite State Machine還允許指定錯誤處理函數(shù),當(dāng)發(fā)生了當(dāng)前狀態(tài)不可能發(fā)生的事件時自動觸發(fā)。 ```javascript var fsm = StateMachine.create({   // ...   error: function(eventName, from, to, args, errorCode, errorMessage) {     return 'event ' + eventName + ': ' + errorMessage;   },   // ... }); ``` 比如,當(dāng)前狀態(tài)是green,理論上這時只可能發(fā)生warn事件。要是這時發(fā)生了stop事件,就會觸發(fā)上面的錯誤處理函數(shù)。 Javascript Finite State Machine的基本用法就是上面這些,更詳細的介紹可以參見它的[主頁](https://github.com/jakesgordon/javascript-state-machine)。 <h2 id="9.3">MVC框架與Backbone.js</h2> ## MVC框架 隨著JavaScript程序變得越來越復(fù)雜,往往需要一個團隊協(xié)作開發(fā),這時代碼的模塊化和組織規(guī)范就變得異常重要了。MVC模式就是代碼組織的經(jīng)典模式。 (……MVC介紹。) **(1)Model** Model表示數(shù)據(jù)層,也就是程序需要的數(shù)據(jù)源,通常使用JSON格式表示。 **(2)View** View表示表現(xiàn)層,也就是用戶界面,對于網(wǎng)頁來說,就是用戶看到的網(wǎng)頁HTML代碼。 **(3)Controller** Controller表示控制層,用來對原始數(shù)據(jù)(Model)進行加工,傳送到View。 由于網(wǎng)頁編程不同于客戶端編程,在MVC的基礎(chǔ)上,JavaScript社區(qū)產(chǎn)生了各種變體框架MVP(Model-View-Presenter)、MVVM(Model-View-ViewModel)等等,有人就把所有這一類框架的各種模式統(tǒng)稱為MV*。 框架的優(yōu)點在于合理組織代碼、便于團隊合作和未來的維護,缺點在于有一定的學(xué)習(xí)成本,且限制你只能采取它的寫法。 ## 零框架解決方案 MVC框架(尤其是大型框架)有一個嚴重的缺點,就是會產(chǎn)生用戶的重度依賴。一旦框架本身出現(xiàn)問題或者停止更新,用戶的處境就會很困難,維護和更新成本極高。 ES6的到來,使得JavaScript語言有了原生的模塊解決方案。于是,開發(fā)者有了另一種選擇,就是不使用MVC框架,只使用各種單一用途的模塊庫,組合完成一個項目。下面是可供選擇的各種用途的模塊列表。 輔助功能庫(Helper Libraries) - [moment.js](http://momentjs.com/):日期和時間的標(biāo)準(zhǔn)化 - [underscore.js](http://underscorejs.org/) / [Lo-Dash](https://lodash.com/):一系列函數(shù)式編程的功能函數(shù) 路由庫(Routing) - [router.js](https://github.com/tildeio/router.js/):Ember.js使用的路由庫 - [route-recognizer](https://github.com/tildeio/route-recognizer):功能全面的路由庫 - [page.js](https://github.com/visionmedia/page.js):類似Express路由的庫 - [director](https://github.com/flatiron/director):同時支持服務(wù)器和瀏覽器的路由庫 Promise庫 - [RSVP.js](https://github.com/tildeio/rsvp.js):ES6兼容的Promise庫 - [ES6-Promise](https://github.com/jakearchibald/es6-promise):RSVP.js的子集,但是全面兼容ES6 - [q](https://github.com/kriskowal/q):最常用的Promise庫之一,AngularJS用了它的精簡版 - [native-promise-only](https://github.com/getify/native-promise-only):嚴格符合ES6的Promise標(biāo)準(zhǔn),同時兼容老式瀏覽器 客戶端與服務(wù)器的通信庫 - [fetch](https://github.com/github/fetch):實現(xiàn)window.fetch功能 - [qwest](https://github.com/pyrsmk/qwest):支持XHR2和Promise的Ajax庫 - [jQuery](https://github.com/jquery/jquery):jQuery 2.0支持按模塊打包,因此可以創(chuàng)建一個純Ajax功能庫 動畫庫(Animation) - [cssanimevent](https://github.com/magnetikonline/cssanimevent):兼容老式瀏覽器的CSS3動畫庫 - [Velocity.js](http://julian.com/research/velocity/):性能優(yōu)秀的動畫庫 輔助開發(fā)庫(Development Assistance) - [LogJS](https://github.com/bfattori/LogJS):輕量級的logging功能庫 - [UserTiming.js](https://github.com/nicjansma/usertiming.js):支持老式瀏覽器的高精度時間戳庫 流程控制和架構(gòu)(Flow Control/Architecture) - [ondomready](https://github.com/tubalmartin/ondomready):類似jQuery的ready()方法,符合AMD規(guī)范 - [script.js](https://github.com/ded/script.js]):異步的腳本加載和依賴關(guān)系管理庫 - [async](https://github.com/caolan/async):瀏覽器和node.js的異步管理工具庫 - [Virtual DOM](https://github.com/Matt-Esch/virtual-dom):react.js的一個替代方案,參見[Virtual DOM and diffing algorithm](https://gist.github.com/Raynos/8414846) 數(shù)據(jù)綁定(Data-binding) - Object.observe():Chrome已經(jīng)支持該方法,可以輕易實現(xiàn)雙向數(shù)據(jù)綁定 模板庫(Templating) - [Mustache](http://mustache.github.io/):大概是目前使用最廣的不含邏輯的模板系統(tǒng) 微框架(Micro-Framework) 某些情況下,可以使用微型框架,作為項目開發(fā)的起點。 - [bottlejs](https://github.com/young-steveo/bottlejs):提供惰性加載、中間件鉤子、裝飾器等功能 - [Stapes.js](http://hay.github.io/stapes/#top):微型MVC框架 - [soma.js](http://somajs.github.io/somajs/site/):提供一個松耦合、易測試的架構(gòu) - [knockout](http://knockoutjs.com/):最流行的微框架之一,主要關(guān)注UI ## Backbone的加載 ```html <script src="/javascripts/lib/jquery.js"></script> <script src="/javascripts/lib/underscore.js"></script> <script src="/javascripts/lib/backbone.js"></script> <script src="/javascripts/jst.js"></script> <script src="/javascripts/router.js"></script> <script src="/javascripts/init.js"></script> ``` ## Backbone的用法 Backbone是最早的JavaScript MVC框架,也是最簡化的一個框架。它的設(shè)計思想是,只提供最基本的功能,給用戶提供最大的自由。這意味著,好的一面是它沒有一整套規(guī)則,強制你接受,壞的一面是很多功能你必須自己實現(xiàn)。Backbone的體積相當(dāng)小,最小化后只有30多KB。 定義一個對象,表示W(wǎng)eb應(yīng)用。 ```javascript var AppName = { Models :{}, Views :{}, Collections :{}, Controllers :{} }; ``` 上面代碼表示,應(yīng)用由四部分組成:Model、Collection、Controller和View。 定義Model,表示數(shù)據(jù)的一個基本單位。 ```javascript AppName.Models.Person = Backbone.Model.extend({ urlRoot: "/persons" }); ``` 定義Collection,表示Model的集合。 ```javascript AppName.Collections.Library = Backbone.Collection.extend({ model: AppName.Models.Book }); ``` 上面代碼表示,Collection對象必須有model屬性,指明由哪一個model構(gòu)成。 定義一個View。 ```javascript AppName.Views.Modals.AcceptDecline = Backbone.View.Extend({ el: ".modal-accept", events: { "ajax:success .link-accept" :"acceptSuccess", "ajax:error .link-accept" :"acceptError" }, acceptSuccess :function(evt, response) { this.$el.modal("hide"); alert('Cool! Thanks'); }, acceptError :function(evt, response) { var $modalContent = this.$el.find('.panel-modal'); $modalContent.append("Something was wrong!"); } }); ``` View對象必須有el屬性,指明當(dāng)前View綁定的DOM節(jié)點,events屬性指明事件和對應(yīng)的方法。 定義一個Controller。 ```javascript AppName.Controllers.Person = {}; AppName.Controllers.Person.show = function(id) { var aMa = new AppName.Models.Person({id: id}); aMa.updateAge(25); aMa.fetch().done(function(){ var view = new AppName.Views.Show({model: aMa}); }); }; ``` 最后,定義路由,啟動應(yīng)用程序。 ```javascript var Workspace = Backbone.Router.extend({ routes: { "*" :"wholeApp", "users/:id" :"usersShow", "users/:id/orders/" :"ordersIndex" }, wholeApp :AppName.Controller.Application.default, usersShow :AppName.Controller.Users.show, ordersIndex :AppName.Controller.Orders.index }); new Workspace(); Backbone.history.start({pushState: true}); ``` ## Backbone.View ### 基本用法 Backbone.View方法用于定義視圖類。 ```javascrip var AppView = Backbone.View.extend({ render: function(){ $('main').append('<h1>一級標(biāo)題</h1>'); } }); ``` 上面代碼通過Backbone.View的extend方法,定義了一個視圖類AppView。該類內(nèi)部有一個render方法,用于將視圖放置在網(wǎng)頁上。 使用的時候,需要先新建視圖類的實例,然后通過實例,調(diào)用render方法,從而讓視圖在網(wǎng)頁上顯示。 ```javascript var appView = new AppView(); appView.render(); ``` 上面代碼新建視圖類AppView的實例appView,然后調(diào)用appView.render,網(wǎng)頁上就會顯示指定的內(nèi)容。 新建視圖實例時,通常需要指定Model。 ```javascript var document = new Document({ model: doc }); ``` ### initialize方法 視圖還可以定義initialize方法,生成實例的時候,會自動調(diào)用該方法對實例初始化。 ```javascript var AppView = Backbone.View.extend({ initialize: function(){ this.render(); }, render: function(){ $('main').append('<h1>一級標(biāo)題</h1>'); } }); var appView = new AppView(); ``` 上面代碼定義了initialize方法之后,就省去了生成實例后,手動調(diào)用appView.render()的步驟。 ### el屬性,$el屬性 除了直接在render方法中,指定“視圖”所綁定的網(wǎng)頁元素,還可以用視圖的el屬性指定網(wǎng)頁元素。 ```javascript var AppView = Backbone.View.extend({ el: $('main'), render: function(){ this.$el.append('<h1>一級標(biāo)題</h1>'); } }); ``` 上面的代碼與render方法直接綁定網(wǎng)頁元素,效果完全一樣。上面代碼中,除了el屬性,還是$el屬性,前者代表指定的DOM元素,后者則表示該DOM元素對應(yīng)的jQuery對象。 ### tagName屬性,className屬性 如果不指定el屬性,也可以通過tagName屬性和className屬性指定。 ```javascript var Document = Backbone.View.extend({ tagName: "li", className: "document", render: function() { // ... } }); ``` ### template方法 視圖的template屬性用來指定網(wǎng)頁模板。 ```javascript var AppView = Backbone.View.extend({ template: _.template("<h3>Hello <%= who %><h3>"), }); ``` 上面代碼中,underscore函數(shù)庫的template函數(shù),接受一個模板字符串作為參數(shù),返回對應(yīng)的模板函數(shù)。有了這個模板函數(shù),只要提供具體的值,就能生成網(wǎng)頁代碼。 ```javascript var AppView = Backbone.View.extend({ el: $('#container'), template: _.template("<h3>Hello <%= who %><h3>"), initialize: function(){ this.render(); }, render: function(){ this.$el.html(this.template({who: 'world!'})); } }); ``` 上面代碼的render就調(diào)用了template方法,從而生成具體的網(wǎng)頁代碼。 實際應(yīng)用中,一般將模板放在script標(biāo)簽中,為了防止瀏覽器按照JavaScript代碼解析,type屬性設(shè)為text/template。 ```html <script type="text/template" data-name="templateName"> <!-- template contents goes here --> </script> ``` 可以使用下面的代碼編譯模板。 ```javascript window.templates = {}; var $sources = $('script[type="text/template"]'); $sources.each(function(index, el) { var $el = $(el); templates[$el.data('name')] = _.template($el.html()); }); ``` ### events屬性 events屬性用于指定視圖的事件及其對應(yīng)的處理函數(shù)。 ```javascript var Document = Backbone.View.extend({ events: { "click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" } }); ``` 上面代碼中一個指定了三個CSS選擇器的單擊事件,及其對應(yīng)的三個處理函數(shù)。 ### listento方法 listento方法用于為特定事件指定回調(diào)函數(shù)。 ```javascript var Document = Backbone.View.extend({ initialize: function() { this.listenTo(this.model, "change", this.render); } }); ``` 上面代碼為model的change事件,指定了回調(diào)函數(shù)為render。 ### remove方法 remove方法用于移除一個視圖。 ```javascript updateView: function() { view.remove(); view.render(); }; ``` ### 子視圖(subview) 在父視圖中可以調(diào)用子視圖。下面就是一種寫法。 ```javascript render : function (){ this.$el.html(this.template()); this.child = new Child(); this.child.appendTo($.('.container-placeholder').render(); } ``` ## Backbone.Events `Backbone.Events`是一個事件對象。任何繼承了這個對象的對象,都具備了`Backbone.Events`的事件接口,可以調(diào)用on和trigger方法,發(fā)布和訂閱消息。 ```javascript var EventChannel = _.extend({}, Backbone.Events); ``` 下面是一些例子。 ```javascript var channel = $.extend( {}, Backbone.Events ); channel.on('remove-node', function(msg) { // code to remove the node }); channel.trigger( 'remove-node', msg ); // 'msg' can be everything: String, number, object and so forth // also we can pass more than one message like the example below channel.on('add-node', function(node, callback) { // code to add a new node callback(); } ); channel.trigger('add-node', { label: 'I am a new node', color: 'black' }, function() { console.log( 'I am a callback' ); }); ``` ## Backbone.Router Router是Backbone提供的路由對象,用來將用戶請求的網(wǎng)址與后端的處理函數(shù)一一對應(yīng)。 首先,新定義一個Router類。 ```javascript Router = Backbone.Router.extend({ routes: { } }); ``` ## routes屬性 Backbone.Router對象中,最重要的就是routes屬性。它用來設(shè)置路徑的處理方法。 routes屬性是一個對象,它的每個成員就代表一個路徑處理規(guī)則,鍵名為路徑規(guī)則,鍵值為處理方法。 如果鍵名為空字符串,就代表根路徑。 ```javascript routes: { '': 'phonesIndex', }, phonesIndex: function () { new PhonesIndexView({ el: 'section#main' }); } ``` 星號代表任意路徑,可以設(shè)置路徑參數(shù),捕獲具體的路徑值。 ```javascript var AppRouter = Backbone.Router.extend({ routes: { "*actions": "defaultRoute" } }); var app_router = new AppRouter; app_router.on('route:defaultRoute', function(actions) { console.log(actions); }) ``` 上面代碼中,根路徑后面的參數(shù),都會被捕獲,傳入回調(diào)函數(shù)。 路徑規(guī)則的寫法。 ```javascript var myrouter = Backbone.Router.extend({ routes: { "help": "help", "search/:query": "search" }, help: function() { ... }, search: function(query) { ... } }); routes: { "help/:page": "help", "download/*path": "download", "folder/:name": "openFolder", "folder/:name-:mode": "openFolder" } router.on("route:help", function(page) { ... }); ``` ## Backbone.history 設(shè)置了router以后,就可以啟動應(yīng)用程序。Backbone.history對象用來監(jiān)控url的變化。 ```javascript App = new Router(); $(document).ready(function () { Backbone.history.start({ pushState: true }); }); ``` 打開pushState方法。如果應(yīng)用程序不在根目錄,就需要指定根目錄。 ```javascript Backbone.history.start({pushState: true, root: "/public/search/"}) ``` ## Backbone.Model Model代表單個的對象實體。 ```javascript var User = Backbone.Model.extend({ defaults: { name: '', email: '' } }); var user = new User(); ``` 上面代碼使用extend方法,生成了一個User類,它代表model的模板。然后,使用new命令,生成一個Model的實例。defaults屬性用來設(shè)置默認屬性,上面代碼表示user對象默認有name和email兩個屬性,它們的值都等于空字符串。 生成實例時,可以提供各個屬性的具體值。 ```javascript var user = new User ({ id: 1, name: 'name', email: 'name@email.com' }); ``` 上面代碼在生成實例時,提供了各個屬性的具體值。 ### idAttribute屬性 Model實例必須有一個屬性,作為區(qū)分其他實例的主鍵。這個屬性的名稱,由idAttribute屬性設(shè)定,一般是設(shè)為id。 ```javascript var Music = Backbone.Model.extend({ idAttribute: 'id' }); ``` ### get方法 get方法用于返回Model實例的某個屬性的值。 ```javascript var user = new User({ name: "name", age: 24}); var age = user.get("age"); // 24 var name = user.get("name"); // "name" ``` ### set方法 set方法用于設(shè)置Model實例的某個屬性的值。 ```javascript var User = Backbone.Model.extend({ buy: function(newCarsName){ this.set({car: newCarsName }); } }); var user = new User({name: 'BMW',model:'i8',type:'car'}); user.buy('Porsche'); var car = user.get("car"); // ‘Porsche’ ``` ### on方法 on方法用于監(jiān)聽對象的變化。 ```javascript var user = new User({name: 'BMW',model:'i8'}); user.on("change:name", function(model){ var name = model.get("name"); // "Porsche" console.log("Changed my car’s name to " + name); }); user.set({name: 'Porsche'}); // Changed my car’s name to Porsche ``` 上面代碼中的on方法用于監(jiān)聽事件,“change:name”表示name屬性發(fā)生變化。 ### urlroot屬性 該屬性用于指定服務(wù)器端對model進行操作的路徑。 ```javascript var User = Backbone.Model.extend({ urlRoot: '/user' }); ``` 上面代碼指定,服務(wù)器對應(yīng)該Model的路徑為/user。 ### fetch事件 fetch事件用于從服務(wù)器取出Model。 ```javascript var user = new User ({id: 1}); user.fetch({ success: function (user){ console.log(user.toJSON()); } }) ``` 上面代碼中,user實例含有id屬性(值為1),fetch方法使用HTTP動詞GET,向網(wǎng)址“/user/1”發(fā)出請求,從服務(wù)器取出該實例。 ### save方法 save方法用于通知服務(wù)器新建或更新Model。 如果一個Model實例不含有id屬性,則save方法將使用POST方法新建該實例。 ```javascript var User = Backbone.Model.extend({ urlRoot: '/user' }); var user = new User (); var userDetails = { name: 'name', email: 'name@email.com' }; user.save(userDetails, { success: function (user) { console.log(user.toJSON()); } }) ``` 上面代碼先在類中指定Model對應(yīng)的網(wǎng)址是/user,然后新建一個實例,最后調(diào)用save方法。它有兩個參數(shù),第一個是實例對象的具體屬性,第二個參數(shù)是一個回調(diào)函數(shù)對象,設(shè)定success事件(保存成功)的回調(diào)函數(shù)。具體來說,save方法會向/user發(fā)出一個POST請求,并將{name: 'name', email: 'name@email.com'}作為數(shù)據(jù)提供。 如果一個Model實例含有id屬性,則save方法將使用PUT方法更新該實例。 ```javascript var user = new User ({ id: 1, name: '張三', email: 'name@email.com' }); user.save({name: '李四'}, { success: function (model) { console.log(user.toJSON()); } }); ``` 上面代碼中,對象實例含有id屬性(值為1),save將使用PUT方法向網(wǎng)址“/user/1”發(fā)出請求,從而更新該實例。 ### destroy方法 destroy方法用于在服務(wù)器上刪除該實例。 ```javascript var user = new User ({ id: 1, name: 'name', email: 'name@email.com' }); user.destroy({ success: function () { console.log('Destroyed'); } }); ``` 上面代碼的destroy方法,將使用HTTP動詞DELETE,向網(wǎng)址“/user/1”發(fā)出請求,刪除對應(yīng)的Model實例。 ## Backbone.Collection Collection是同一類Model的集合,比如Model是動物,Collection就是動物園;Model是單個的人,Collection就是一家公司。 ```javascript var Song = Backbone.Model.extend({}); var Album = Backbone.Collection.extend({ model: Song }); ``` 上面代碼中,Song是Model,Album是Collection,而且Album有一個model屬性等于Song,因此表明Album是Song的集合。 ### add方法,remove方法 Model的實例可以直接放入Collection的實例,也可以用add方法添加。 ```javascript var song1 = new Song({ id: 1 ,name: "歌名1", artist: "張三" }); var song2 = new Music ({id: 2,name: "歌名2", artist: "李四" }); var myAlbum = new Album([song1, song2]); var song3 = new Music({ id: 3, name: "歌名3",artist:"趙五" }); myAlbum.add(song3); ``` remove方法用于從Collection實例中移除一個Model實例。 ```javascript myAlbum.remove(1); ``` 上面代碼表明,remove方法的參數(shù)是model實例的id屬性。 ### get方法,set方法 get方法用于從Collection中獲取指定id的Model實例。 ```javascript myAlbum.get(2)) ``` ### fetch方法 fetch方法用于從服務(wù)器取出Collection數(shù)據(jù)。 ```javascript var songs = new Backbone.Collection; songs.url = '/songs'; songs.fetch(); ``` ## Backbone.events ```javascript var obj = {}; _.extend(obj, Backbone.Events); obj.on("show-message", function(msg) { $('#display').text(msg); }); obj.trigger("show-message", "Hello World"); ``` <h2 id="9.4">嚴格模式</h2> ## 概述 ### 設(shè)計目的 除了正常運行模式,ECMAScript 5添加了第二種運行模式:“嚴格模式”(strict mode)。顧名思義,這種模式使得JavaScript在更嚴格的條件下運行。 設(shè)立”嚴格模式“的目的,主要有以下幾個: - 消除JavaScript語法的一些不合理、不嚴謹之處,減少一些怪異行為; - 增加更多報錯的場合,消除代碼運行的一些不安全之處,保證代碼運行的安全; - 提高編譯器效率,增加運行速度; - 為未來新版本的JavaScript做好鋪墊。 “嚴格模式”體現(xiàn)了JavaScript更合理、更安全、更嚴謹?shù)陌l(fā)展方向。 同樣的代碼,在”正常模式“和”嚴格模式“中,可能會有不一樣的運行結(jié)果。一些在"正常模式"下可以運行的語句,在"嚴格模式"下將不能運行。掌握這些內(nèi)容,有助于更細致深入地理解JavaScript,讓你變成一個更好的程序員。 ### 啟用方法 進入“嚴格模式”的標(biāo)志,是一行字符串`use strict`。 ```javascript 'use strict'; ``` 老版本的瀏覽器會把它當(dāng)作一行普通字符串,加以忽略。新版本的瀏覽器就會進入嚴格模式。 “嚴格模式”可以用于整個腳本,也可以只用于單個函數(shù)。 **(1) 針對整個腳本文件** 將`use strict`放在腳本文件的第一行,則整個腳本都將以“嚴格模式”運行。如果這行語句不在第一行就無效,整個腳本會以“正常模式”運行。(嚴格地說,只要前面不是產(chǎn)生實際運行結(jié)果的語句,`use strict`可以不在第一行,比如直接跟在一個空的分號后面,或者跟在注釋后面。) ```html <script> 'use strict'; console.log('這是嚴格模式'); </script> <script> console.log('這是正常模式'); </script> ``` 上面的代碼表示,一個網(wǎng)頁文件中依次有兩段JavaScript代碼。前一個`<script>`標(biāo)簽是嚴格模式,后一個不是。 如果字符串`use strict`出現(xiàn)在代碼中間,則不起作用,即嚴格模式必須從代碼一開始就生效。 兩個不同模式的腳本合并成一個文件,如果嚴格模式的腳本在前,則合并后的腳本都是”嚴格模式“;如果正常模式的腳本在前,則合并后的腳本都是”正常模式“??傊@兩種情況下,合并后的結(jié)果都是不正確的。因此,建議在多個腳本需要合并的場合,”嚴格模式“只在函數(shù)中打開,不針對整個腳本打開。 **(2)針對單個函數(shù)** 將“use strict”放在函數(shù)體的第一行,則整個函數(shù)以“嚴格模式”運行。 ```javascript function strict() { 'use strict'; return '這是嚴格模式'; } function notStrict() { return '這是正常模式'; } ``` **(3)腳本文件的變通寫法** 因為在腳本文件第一行放置`use strict`不利于文件合并,所以更好的做法是,借用第二種方法,將整個腳本文件放在一個立即執(zhí)行的匿名函數(shù)之中。 ```javascript (function () { "use strict"; // some code here })(); ``` ## 顯式報錯 嚴格模式使得JavaScript的語法變得更嚴格,更多的操作會顯式報錯。其中有些操作,在正常模式下只會默默地失敗,不會報錯。 ### 字符串的length屬性不可寫 嚴格模式下,設(shè)置字符串的`length`屬性,會報錯。 ```javascript 'use strict'; 'abc'.length = 5; ``` 實際上,嚴格模式下,對只讀屬性賦值,或者刪除不可配置(nonconfigurable)屬性都會報錯。 ### eval、arguments不可用作函數(shù)名 使用`eval`,或者在函數(shù)內(nèi)部使用`arguments`,作為標(biāo)識名,將會報錯。 下面的語句都會報錯。 ```javascript 'use strict'; eval = 17; arguments++; ++eval; var obj = { set p(arguments) { } }; var eval; try { } catch (arguments) { } function x(eval) { } function arguments() { } var y = function eval() { }; var f = new Function("arguments", "'use strict'; return 17;"); ``` ### 只讀屬性不可寫 正常模式下,對一個對象的只讀屬性進行賦值,不會報錯,只會默默地失敗。嚴格模式下,將報錯。 ```javascript 'use strict'; var o = {}; Object.defineProperty(o, 'v', { value: 1, writable: false }); o.v = 2; // 報錯 ``` ### 只設(shè)置了賦值器的屬性不可寫 嚴格模式下,對一個只設(shè)置了賦值器(getter)的屬性賦值,會報錯。 ```javascript "use strict"; var o = { get v() { return 1; } }; o.v = 2; // 報錯 ``` ### 禁止擴展的對象不可擴展 嚴格模式下,對禁止擴展的對象添加新屬性,會報錯。 ```javascript 'use strict'; var o = {}; Object.preventExtensions(o); o.v = 1; // 報錯 ``` ### 禁止刪除不可刪除的屬性 嚴格模式下,刪除一個不可刪除的屬性,會報錯。 ```javascript 'use strict'; delete Object.prototype; // 報錯 ``` ### 函數(shù)不能有重名的參數(shù) 正常模式下,如果函數(shù)有多個重名的參數(shù),可以用`arguments[i]`讀取。嚴格模式下,這屬于語法錯誤。 ```javascript function f(a, a, b) { // 語法錯誤 'use strict'; return a + b; } ``` ### 禁止八進制的前綴0表示法 正常模式下,整數(shù)的第一位如果是`0`,表示這是八進制數(shù),比如`0100`等于十進制的64。嚴格模式禁止這種表示法,整數(shù)第一位為`0`,將報錯。 ```javascript "use strict"; var n = 0100; // SyntaxError ``` ## 增強的安全措施 嚴格模式增強了安全保護,從語法上防止了一些不小心會出現(xiàn)的錯誤。 ### 全局變量顯式聲明 在正常模式中,如果一個變量沒有聲明就賦值,默認是全局變量。嚴格模式禁止這種用法,全局變量必須顯式聲明。 ```javascript 'use strict'; v = 1; // 報錯,v未聲明 for (i = 0; i < 2; i++) { // 報錯,i未聲明 // ... } function f() { x = 123; } f() // 報錯,未聲明就創(chuàng)建一個全局變量 ``` 因此,嚴格模式下,變量都必須先用`var`命令聲明,然后再使用。 ### 禁止this關(guān)鍵字指向全局對象 正常模式下,函數(shù)內(nèi)部的`this`可能會指向全局對象,嚴格模式禁止這種用法,避免無意間創(chuàng)造全局變量。 ```javascript // 正常模式 function f() { console.log(this === window); } f() // true // 嚴格模式 function f() { 'use strict'; console.log(this === undefined); } f() // true ``` 這種限制對于構(gòu)造函數(shù)尤其有用。使用構(gòu)造函數(shù)時,有時忘了加`new`,這時`this`不再指向全局對象,而是報錯。 ```javascript function f() { 'use strict'; this.a = 1; }; f();// 報錯,this未定義 ``` 嚴格模式下,函數(shù)直接調(diào)用時(不使用`new`調(diào)用),函數(shù)內(nèi)部的`this`表示`undefined`,因此可以用`call`、`apply`和`bind`方法,將任意值綁定在`this`上面。 ```javascript 'use strict'; function fun() { return this; } fun() //undefined fun.call(2) // 2 fun.apply(null) // null fun.call(undefined) // undefined fun.bind(true)() // true ``` ### 禁止使用fn.callee、fn.caller 函數(shù)內(nèi)部不得使用`fn.caller`、`fn.arguments`,否則會報錯。這意味著不能在函數(shù)內(nèi)部得到調(diào)用棧了。 ```javascript function f1() { 'use strict'; f1.caller; // 報錯 f1.arguments; // 報錯 } f1(); ``` ### 禁止使用arguments.callee、arguments.caller `arguments.callee`和`arguments.caller`是兩個歷史遺留的變量,從來沒有標(biāo)準(zhǔn)化過,現(xiàn)在已經(jīng)取消了。正常模式下調(diào)用它們沒有什么作用,但是不會報錯。嚴格模式明確規(guī)定,函數(shù)內(nèi)部使用`arguments.callee`、`arguments.caller`將會報錯。 ```javascript 'use strict'; var f = function() { return arguments.callee; }; f(); // 報錯 ``` ### 禁止刪除變量 嚴格模式下無法刪除變量,如果使用`delete`命令刪除一個變量,會報錯。只有對象的屬性,且屬性的描述對象的`configurable`屬性設(shè)置為true,才能被`delete`命令刪除。 ```javascript "use strict"; var x; delete x; // 語法錯誤 var o = Object.create(null, { x: { value: 1, configurable: true } }); delete o.x; // 刪除成功 ``` ## 靜態(tài)綁定 JavaScript語言的一個特點,就是允許“動態(tài)綁定”,即某些屬性和方法到底屬于哪一個對象,不是在編譯時確定的,而是在運行時(runtime)確定的。 嚴格模式對動態(tài)綁定做了一些限制。某些情況下,只允許靜態(tài)綁定。也就是說,屬性和方法到底歸屬哪個對象,必須在編譯階段就確定。這樣做有利于編譯效率的提高,也使得代碼更容易閱讀,更少出現(xiàn)意外。 具體來說,涉及以下幾個方面。 ### 禁止使用with語句 嚴格模式下,使用`with`語句將報錯。因為`with`語句無法在編譯時就確定,某個屬性到底歸屬哪個對象,從而影響了編譯效果。 ```javascript 'use strict'; var v = 1; with (o) { // SyntaxError v = 2; } ``` ### 創(chuàng)設(shè)eval作用域 正常模式下,JavaScript語言有兩種變量作用域(scope):全局作用域和函數(shù)作用域。嚴格模式創(chuàng)設(shè)了第三種作用域:`eval`作用域。 正常模式下,`eval`語句的作用域,取決于它處于全局作用域,還是函數(shù)作用域。嚴格模式下,`eval`語句本身就是一個作用域,不再能夠在其所運行的作用域創(chuàng)設(shè)新的變量了,也就是說,`eval`所生成的變量只能用于`eval`內(nèi)部。 ```javascript (function () { 'use strict'; var x = 2; console.log(eval('var x = 5; x')) // 5 console.log(x) // 2 })() ``` 注意,如果希望`eval`語句也使用嚴格模式,有兩種方式。 ```javascript // 方式一 function f1(str){ 'use strict'; return eval(str); } f1('undeclared_variable = 1'); // 報錯 // 方式二 function f2(str){ return eval(str); } f2('"use strict";undeclared_variable = 1') // 報錯 ``` 上面兩種寫法,`eval`內(nèi)部使用的都是嚴格模式。 ### arguments不再追蹤參數(shù)的變化 變量`arguments`代表函數(shù)的參數(shù)。嚴格模式下,函數(shù)內(nèi)部改變參數(shù)與`arguments`的聯(lián)系被切斷了,兩者不再存在聯(lián)動關(guān)系。 ```javascript function f(a) { a = 2; return [a, arguments[0]]; } f(1); // 正常模式為[2, 2] function f(a) { "use strict"; a = 2; return [a, arguments[0]]; } f(1); // 嚴格模式為[2, 1] ``` 上面代碼中,改變函數(shù)的參數(shù),不會反應(yīng)到`arguments`對象上來。 ## 向下一個版本的JavaScript過渡 JavaScript語言的下一個版本是ECMAScript 6,為了平穩(wěn)過渡,嚴格模式引入了一些ES6語法。 ### 函數(shù)必須聲明在頂層 JavaScript的新版本ES6會引入“塊級作用域”。為了與新版本接軌,嚴格模式只允許在全局作用域或函數(shù)作用域的頂層聲明函數(shù)。也就是說,不允許在非函數(shù)的代碼塊內(nèi)聲明函數(shù)。 ```javascript "use strict"; if (true) { function f1() { } // 語法錯誤 } for (var i = 0; i < 5; i++) { function f2() { } // 語法錯誤 } ``` 上面代碼在`if`代碼塊和`for`代碼塊中聲明了函數(shù),在嚴格模式下都會報錯。 ### 保留字 為了向?qū)鞪avaScript的新版本過渡,嚴格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。 使用這些詞作為變量名將會報錯。 ```javascript function package(protected) { // 語法錯誤 'use strict'; var implements; // 語法錯誤 } ``` 此外,ECMAscript第五版本身還規(guī)定了另一些保留字(`class`, `enum`, `export`, `extends`, `import`, `super`),以及各大瀏覽器自行增加的`const`保留字,也是不能作為變量名的。
av日韩在线有码a区| 精品久久一区电影亚洲| 成人精品一区一区二区看片| 久久久久久少妇被弄高潮| 97久久碰人妻一区二区三区四 | 熟女人妻之中文字幕| 久久成人网男人的天堂| 亚洲伊人网在线播放| 亚洲一级av大片| 亚洲成a人片,77777| 乱丰满的岳伦在线观看| www.199麻豆在线视频| 亚洲成人日韩丶av| 国产青青91av在线视频| 日韩亚洲图色在线| 91综合精品国产丝袜长腿| 欧美一区二区三区激情啪啪啪| 日韩av在线不卡网站| 久久av资源男人站| 牛牛成人手机视频在线| 91在线精品国自产拍| 中文字幕av最新资源| 91嫩草17c欧美国产| 麻豆亚州av熟女国产一区二| 亚洲欧美自拍偷拍在线观看| 欧美中文字幕在线一区| 亚洲国产精品午夜av| 五月婷婷久久久久久久久| 亚洲五月婷婷激情图片| 亚洲另类色区欧美日韩| 在线免费av大香蕉| 久久久久久久精品综合| 欧美一区二区理论片在线观看| 麻豆成人在线免费观看视频| 免费观看a级在线视频| 欧美日韩在线卡一卡二卡三| 久久久久女优免费视频| 精品国产乱码久久久久久蜜坠欲下| 成人av电影免费版| 欧美日韩人妻久久精品| 亚洲激情熟女色图| 97久久碰人妻一区二区三区四| 欧美一区二区三区成人免费看| 欧美日韩精品成人在线| 日韩精品综合免费视频| 精品美女1区2区3区| 亚洲激情 欧美激情| 91人妻九色大屁股| 欧美一区二区三区成人久久片| av传媒高清影院免费| av色香蕉一区二区三区| 久久行黑国产露脸精品| av在线免费播放成人| 亚洲图色91东京热| 俺去鲁婷婷六月色综合| 精品久久久久久999| 熟女人妻之中文字幕 | 日韩成视频在线播放| 国产精品久久久久久久久粉嫩av| 国产99不卡免费在线观看| 久久国产精品人妻酒店| 国产成人精品久久综合| 国产欧美日韩不卡在线观看| 人人妻人人爱碰千| 男人的天堂久久久亚洲| 福利一福利二福利三| 思思久久国产精品视频| 日韩国产精品电影网| 日本av男优巧克力| 色婷婷久久久swag精品| 在线观看日韩中文| 亚洲 自拍偷拍 欧美| 91影视一区二区三区| 一本久久久久久久18| 之久精品一区二区| 久久视频这里都是精品| 久久久久久久久久久久久丰满| 日韩亚洲图色在线| 欧美日韩激情在线视频观看| 久久传奇网站一区三区视频| 国产成人av最新网址| 国产亚洲天堂sss| 国内精品久久久久久久久久清纯| 国产成人一区二区三区在线视频| 日韩亚洲图色在线| 天天日天天干天天爱天天| 97久久视频免费在线播放| 日本二次元少女裸| japanese 在线中文字幕| 日韩人妻插舔激情午夜| 日韩在线中文字幕不卡| 人妻熟女视频免费观看| 99久久窝窝午夜影视| 97精品久久人人爽人人爽| av国产一区二区三区| 久久最近最新中文字幕大全| 青青青在线视频自拍| 午夜精品福利小视频| av传媒高清影院免费| 国产成人无码AA精品一区 | 亚洲欧美在线制服丝袜| 久久久精品国产亚洲av网深田| av国产一区二区三区| av福利网站在线观看| 黑人操日本女人电影| av熟妇翔田千里俱乐部| 67914熟女在线观看| 99九九99九九热视频| 亚洲视频另类专区| 国产一区二区免费五遮挡| 亚洲欧美在线制服丝袜| 在线观看色有小视频| 久久一本麻豆天美欧美日韩| 亚洲国产精品国自产拍av麻豆| 久久久亚洲在线视频| 美女18禁久久久久麻豆| 天天干天天天天射天天操| 国产精品一区二区三区三级 | 美女在线观看亚洲一区| 少妇惨叫久久久久久久| 久久综合中文字幕一区二区三区| 国产a级片免费在线观看| 99精品高清免费在线视频| 亚洲青青青国产观看视频| 国产日韩欧美春色另类小说| 99九九99九九热视频| 亚洲中文字幕成人久久| 欧美日韩亚洲大片在线| 日韩一区二区三区乱码| 色男人天堂东京热| 亚洲国产欧美日本视频| 欧美日韩少妇一二三| 久久在线人妻熟女高清完整版 | 国产清纯白嫩美女无套| 精品人妻一区二区三区人妻视频| 97精品国产自在在线观看蜜臀| 日日日日日夜夜夜夜| 五月综合缴情婷婷六月| 日韩美女在线视频一区| 亚洲精品网站成人久久综合| 1024欧美一区二区看片| 国产+日本+欧美在线观看| 97精品久久人人爽人人爽| 天天日天天干天天爱天天| 四十路av熟女俱乐部| 欧美日韩少妇一二三| 日韩男女av在线观看| 国产精品久久久久久久漫画| 亚洲av综合久久伊人| 欧美老熟妇重口另类xxx| 国产成人av最新网址| 亚洲欧美日韩中出| 色熟女蜜臀又伦av| 精品国产久久久久蜜臀| 国产av在线观看麻豆| 明天我们好好过高清免费| 亚洲av微乳在线| 国产又大又长又粗又硬免费视频 | 中文字幕熟女人妻在线观看| 午夜日韩麻豆福利| 97精品国产自在在线观看蜜臀 | 国产一区二区三区四区中文字幕| 免费观看a级在线视频| 日韩尤物人妻av在线网| 综合激情伊人久久| 乱女乱妇熟女熟妇综合站| 91精品一二三区在线观看| 美国av 在线播放| 最新偷窥偷拍免费视频观看 | 国产av一区二区三区天美| 色婷婷中文字幕基地| 亚洲不卡一区av| 蜜臀av 麻豆av| 亚洲熟妇av日韩熟妇在线| 欧美日韩国产一级一顶级| 青娱乐国产视频盛| 老鸭子在线观看免费播放| 免费中文字幕在线播放| 2020中文字幕在线看电影 | 久久国产精品久久伊人麻豆| 久久蜜桃视频亚洲精品| 色yeye香蕉凹凸人妻三区| 日韩欧美一二三级| 日本女同性恋视频| 91一区二区三区精华液| 青青草成人影院在线观看| 国产精品网址在线观看| 欧美中文字幕久久久| 日韩一级黄色大片免费观看| 18在线观看久久久麻豆| 丰满人妻一区二区三区视频看看| 日韩福利视频在线看| 91免费版下载成人| 91精品人妻一区二区三区四区| 91中文字幕制服诱惑| 免费中文字幕在线播放| 天天射天天舔天天射| 欧美一区二区三区激情无套| 亚洲欧洲黄色图区| 日本高清理论片中文字幕| 麻豆网站在线免费看| 91高级会所在线播放| 国产av一区二区三区天美| 国产精品一区二区久久精品蜜臀| 久久精品熟女人妻一区二区三区| 日韩欧美xxxx大片| 午夜精品福利小视频| 成年美女黄色av网站| 亚洲国产一成人久久精品| 亚洲激情国产一区| 久久综合中文字幕一区二区三区| 精品乱码久久久久久蜜臀| 色婷婷久久久swag精品| 99久久极品蜜桃臀精品久久| 天天日天天干天天色| 久久99精品国产91| 国产69tv精品久久| 热香蕉和冷香蕉功效一样吗| 视频免费在线观看91| 国产亚洲天堂sss| 国产高潮国产高潮久久久久久91| 日韩精品福利性无码专区| 一区二区三区四区中文字幕| 久久久精品99国产国产精| 日韩精品在线播放第三页| 久久av资源男人站| 天天干天天插天天操天天日| 美女免费一二三区视频| 蜜桃视频在线观看一区精品| 秋霞电影韩国一区二区二区三区 | 欧美一区二区三区综合色| 久久 99 精品视频| 亚洲国模私拍视频| 日韩毛片亚洲av| 欧美日韩综合国产精品| 91精品久久久久久久久不卡网站| 天天色综合天天射综合| 国产一区二区不卡91| 久久五月天天婷婷激情综合| av色香蕉一区二区三区| 日本老女人视频在线观看| 精品人妻一区二区三区√| 久久久亚洲精品久久仙| 人妻丰满精品一区二区三区| 人人狠狠久久综合网| 国产精品久久久久久久网站门 | 日韩一区二区三区水蜜桃| 久久在线人妻熟女高清完整版| 激情婷婷综合久久五月天| av传媒高清影院免费| 人妻精品少妇嫩草麻豆| 日韩欧美三级一区二区在线观看 | 男人的天堂久久久亚洲| 国产乱人妻精品久久久| 欧美日韩在线卡一卡二卡三| 日韩精品综合视频在线| 蜜臀av 麻豆av| 日韩成人av在线电影观看| 91高级会所在线播放| 国产成人免费精品视频大全| 日韩av电影免费在线播放| 青青青手机版视频在线看| 成人黄色午夜污网站在线观看| 亚洲国模私拍视频| 亚洲国产一成人久久精品| av福利网站在线观看| 国产黄色主播网址大全在线播放| 人妻精品无码一区二区三区| 色图av亚洲综合| 日本中文字幕久久免费精品| 91麻豆精品91久久久久同性| 久久传奇网站一区三区视频| 另类h小视频在线观看| 蜜臀久久99精品久久久久久久久| 蜜臀av久久久久av蜜臀| 亚洲伊人网在线观看| 亚洲国产精品久久久久婷婷av| 久久精品国产av网| 四十路av熟女俱乐部| 97人人人欧美人人妻人人| 欧美激情 另类视频 亚洲| 97人人人欧美人人妻人人| 亚洲自拍偷拍 av| 亚洲另类色区欧美日韩| 另类h小视频在线观看| 人妻丰满一区二区三区| 亚洲欧洲黄色图区| 亚洲第一黄色天堂| 国产精品网址在线观看| 麻豆亚州av熟女国产一区二| 国产成AV人片在线观看天堂无码| 国产免费一级a男人的天堂| 91久久精品日日躁夜夜躁| 日韩欧美xxxx大片| 精品美女1区2区3区| wwxxx中文字幕| 五月天色婷婷av在线| 国产一区二区三区a级毛片| 日本高清不卡视频在线播放| 精品人妻一区二区三区人妻视频 | 日本黄色成年视频| 97精品久久人人爽人人爽| 日韩卡一卡二卡三卡四卡五| 熟女人妻之中文字幕| 成年人晚上免费看的视频| 在线观看色有小视频| 久久精品中文闷骚内射| 久久精品一区二区三区人妻蜜桃| 欧美日韩精品一区电影| 中文字幕 日本伊人| 国产麻豆剧传媒精品视频| 国产精品福利久久久久久久| 久久亚麻亚洲蜜桃臀| 中文字幕在线有码二区| 日韩视频在线观看一区二区| 五月天色婷婷av在线| 亚洲 欧洲 日韩 人妻| 97久久碰人妻一区二区三区四| 日本熟妇人妻在线| 最新美女激情av| 日韩亚洲丝袜系列| 97精品久久人人爽人人爽| 婷婷中文字幕色婷婷| 亚洲午夜电影久久久| 国产一区二区不卡91| av色香蕉一区二区三区| 日韩在线播放视频1区| 久久久久久夜夜夜精品国产| 亚洲一区二区三二区厕所偷拍| 先锋资源站中文字幕| 久久九特黄的免费大片| 欧美熟女人妻一区二区三区| 久久五月婷婷综合视频| 色哟哟视频在线观看国产| 精品一区二区三区四区人妻69| 97精品国产自在在线观看蜜臀 | 亚洲狠狠婷婷综合久久a| 精品一区二区三区蜜桃臀的优势| 日韩成视频在线播放| 欧美日韩久久久久久精品| 蜜臀av久久久久av蜜臀| 秋霞在线观看色哟哟视频| 日韩精品午夜免费观看| 99国产在线 精品 视频| 欧美日韩综合国产精品| 久久久精品99国产国产精| 91在线播放视频免费| 一本色道久久亚洲综合精品蜜桃| av日韩在线有码a区| 中文字幕精品久久久人妻| 韩国女团午夜大尺度福利| 亚洲人的午夜影院| 国产99不卡免费在线观看| 国产亚洲精久久久久久无码色戒| 欧美日韩激情在线视频观看| 国产精品久久久久久久久粉嫩av| 欧美日韩亚洲大片在线| 91国偷自产一区二区三区老熟女| 久久久国产精品尤物av| 18禁成年av网站免费看| 午夜影院av在线| 精品一区二区三区四区日产| 68国产成人综合久久精品| 日韩在线播放视频1区| 亚洲中文字幕福利视频| 日韩a大片在线观看| 少妇人妻给我内射视频| 91高级会所在线播放| 久久久精品99国产国产精| 久久久久国产精品免费| 久久亚洲精品无码系列客服| 国产网址手机上可以看的国产网站| 天天操天天爽天天舔天天操一操| 视频一区视频二区三区| 亚洲一区二区三二区厕所偷拍| 亚洲狠狠久久综合一区| 男人亚洲天堂2018| 亚洲综合色激情五月| 视频在线观看黄页| 久久亚洲 欧美 综合aⅴ| 精品中文久久久久久| 91精品人妻一区二区三区四区| 中文字幕人妻互换久久视频| 日韩午夜激情福利免费| 影音在线精品免费国产资源| 一级久久久久久久18| 日韩毛片亚洲av| 久久久精品蜜桃在线| 天天干天天插天天操天天日| 国产欧美日韩精品专区黑人| 成人午夜激情福利片| 超碰97在线观看国产| 丰满人妻av白石茉莉奈电影| 日本中文国产字幕| 国产中文字幕在线91| 麻豆成人在线免费观看视频| 久久99久久com| 欧美3d成人动漫在线| 青娱乐国产视频盛| 欧洲av偷拍亚洲av偷拍| 国产成人精品久久久女| 国语黄色淫秽录像带| 精品久久精品久久久久| 人妻中出视频一区二区| 明天我们好好过高清免费| 中文在线字幕a在线| 97cao瑟瑟在线观看| 安斋拉拉中文字幕在线| 亚洲中文字幕成人久久| 久久伊人亚洲综合网| 国产剧情高清在线观看| 日韩欧美在线视频第一页| av成人教育在线播放| 久久国产精品久久伊人麻豆| 最新美女激情av| 久久久久女优免费视频| 亚洲五月婷婷激情图片| 久久久精品蜜桃在线| 国产99精品久久久久久圆免看片| 亚洲乳大丰满中文字幕少妇av| 婷婷免费精品视频在线| 97精品国产自在在线观看蜜臀| 人妻有码中文字幕中文| 国产成AV人片在线观看天堂无码| 日韩在线播放视频1区| 99精品视频69v精品视频| 久久av一区中文字幕| 亚洲欧美在线制服丝袜| 五月黄色激情视频| 日韩欧美xxxx大片| 久久99永久免费看| 久久五月婷婷综合视频| 成人免费av在线网站| 色视频精品视频在线观看| 色噜噜狠狠躁夜夜躁| 欧美日韩精品综合在线一区二区| 肥臀熟女一区二区三区肥女人| 国产欧美日韩精品专区黑人| 久久久久国产麻豆婷婷| 99精品视频在线看17| 亚洲av精品久久久蜜| 99国产在线 精品 视频| 国产成人无码AA精品一区 | 欧美激情电影在线观看不卡| 91一区二区精品在线| 亚洲激情熟女色图| 亚洲香蕉av电影| 日本女优和黑人的| 日本av熟女人妻| 亚洲成年人黄色片| 成年人在线免费观看黄色片| 精品视频在线观看一区二区97| 亚洲男人五月天堂| 国产精品久久久久久吹吹潮| 欧美日韩精品综合在线一区二区| 麻豆丝袜美女人妻中文| 热久久免费频精品18| 精品日韩偷拍欧美另类| 99久久国语露脸精彩对白| 国产熟女高潮av77777| 久久久久久久久久久免费网| 日韩人妻插舔激情午夜 | 麻豆丝袜美女人妻中文| 人人妻人人澡人人爽dv| 国产亚洲av免费一区二区| 色婷婷综合免费在线视频| 99久久极品蜜桃臀精品久久| 篠田优中文字幕在线播| 1024 国产高清の最新合集| 丰满人妻av白石茉莉奈电影| 日韩a大片在线观看| 亚洲av亚洲av亚洲| 亚洲av微乳在线| 色视频在线观看123| 香蕉久久久久久久久久久久女| 久久免费视频观看99| 中文字幕人妻一区二区在线看| 欧美爱情动作片在线一区| 一级久久久久久久18| 国产精品久久久久久久久久网站| 久久国产经典三级av| 欧美一二三区在线观看| 国产天堂avwww| 久久视频一区二区三| 黄色片一级美女黄色片| 国产99不卡免费在线观看| 欧美日本一道本一区二区| 伊人久久中文字幕综合观看| 日韩av 自拍偷拍| 成人黄色国产网站在线观看| 另类蜜桃刺激视频在线观看| 日本高清不卡视频在线播放| 蜜桃久久久一区二区三区| 欧美一区二区三区成人久久片| 国产高潮好爽受不了了视频| 18在线观看久久久麻豆| 亚洲综合在线伊人| 乱丰满的岳伦在线观看| 亚洲男人五月天堂| 在线国产小视频麻豆| 国产亚洲天堂sss| 性欧美另类sex极品free| 日韩av福利大片在线观看| 玖玖玖玖日在线视频| 91在线精品一区二区网站| 日韩视频在线播放一区二区| 99免费观看视频在线| 色丁香婷婷综合久久| 亚洲日本精彩视频在线观看| 精品国产精品视频免费在线观看| 国产高潮国产高潮久久久久久91| 日韩欧美 国产精品| 乱女乱妇熟女熟妇综合站| 999精品插丰满少妇人妻| 中文字幕久久91| 亚洲av微乳在线| 91一区二区精品在线| 亚洲人的午夜影院| 国产黄色主播网址大全在线播放| 国产av在线观看麻豆| 久久这里只有精品久| 影音在线精品免费国产资源| 亚洲精品网站成人久久综合| 三级亚洲天堂亚洲天堂| 亚洲天堂网av中文字幕| 欧美中文字幕久久久| 天天日天天干天天色| 日韩a毛片视频免费看| 日韩视频在线观看一区二区| 国产精品亚洲精品成人| 天天操天天干天天妻| 欧美一区二区三区成人久久片| 搡老熟女一区二区三区四区视频 | 91人妻人人澡.人人精品| 亚洲伊人网在线播放| 日韩中文字幕一区二区三区四区| 在线免费av大香蕉| 亚洲欧美一二三视频| 日韩中文字幕一区二区三区四区 | 99久久999久久久精品综合| 国产精品一区二区三区福利| 一区二区 熟女人妻| 精品国产一区二区三区制服| 欧美成人黄色一区二区三区| 久久人搡人人玩人妻精品| 久久99精品久久久久久三级| 久久爱免费视频16| 高清一区二区日韩视频精品| 久久久精品99国产国产精| 日韩欧美国产成人一区| 亚洲av激情小说| 国产成人一区二区三区在线视频| 亚洲欧美在线制服丝袜| 亚洲成人影院中文字幕| 少妇人妻成人在线| 国产99久久久国产精品成人免费| 五月综合缴情婷婷六月| 国产 欧美 日韩 视频| 91精品国产综合久久久久久粉嫩| 亚洲午夜电影久久久| 亚洲伊人网在线观看| 日韩一区二区三区乱码| 初撮日本五十路人妻| 日韩a大片在线观看| 欧美亚洲av日韩综合一区| 国产91在线播放精品| 日韩乱妇乱女熟妇熟女网红| 亚洲国产精品国自产拍av麻豆| 欧美性久久久久久久久久久| 日韩精品少妇人妻熟女| 国产99精品久久久久久圆免看片| 黄色片一级美女黄色片| 午夜在线观看高清完整版| 欧美中文字幕视频网| 国产精品一区二区久久精品蜜臀| 国产精品一区二区三区三级| sepapa自拍偷拍| 美女18禁久久久久麻豆| 97久久视频免费在线播放| 成人国产一区二区免费| 亚洲欧美日韩综合专区| 日韩av电影在线观看的| 亚洲中文字幕福利视频| 久久久久999蜜桃视频| 日韩成人av在线电影观看| 91老司机免费福利| 日韩国产91综合精品| 亚洲欧美国产另类91综合| 日韩在线免费视频精品| 久久婷婷激情综合色综合俺也去| 日韩a毛片视频免费看| 欧美日韩国产综合aⅴ| 日韩av午夜免费| 亚洲av综合色区手机| 中文字幕精品久久久人妻| 色哟哟免费在线播放| 国产精品成人av在线网站| 欧美中文字幕在线观看视频| 欧美va亚洲va精品| 日韩乱妇乱女熟妇熟女网红| 久久免费视频精彩视频| 人妻中出视频一区二区| 精品人妻久久久久中文字幕19禁| 久久视频免费有精品| 国产av在线观看麻豆| 91一区二区三区精华液| 自拍偷拍 亚洲 在线| 欧美爱情动作片在线一区| 午夜三级中文字幕视频网址大全| 久久九特黄的免费大片| 欧美中文字幕视频网| 欧美肥臀精品一区二区三区| 久久爱免费视频16| 男人的天堂久久久亚洲| 午夜日韩麻豆福利| 久久视频一区二区三| 亚洲不卡一区av| 欧洲av偷拍亚洲av偷拍| 精品激情视频在线免费观看| 亚洲欧美日韩综合专区| 制服巨乳人妻在线| 97人妻人人揉人人澡人人爽国产| 国产黄色主播网址大全在线播放| 美女18禁久久久久麻豆| 午夜日韩麻豆福利| 久久伊人精品青青草原| 亚洲国产精选久久| 明天我们好好过高清免费| 国产麻豆剧传媒精品视频| 国产视频av一区二区| 狠狠久久综合丁香777米奇| 国产一区二区视频大全床| 婷婷激情免费视频| 国产精品99久久电影| 欧美日韩综合国产精品| 久久成人网男人的天堂| 91久久精品日日躁夜夜躁 | 十八禁久久久久久久久久久久久久| 久久人妻少妇嫩草av蜜桃动态图| 欧洲美女黑人粗性暴交视| 国产成人精品视频免费网站| 久久这里只有精品久| 亚洲人妻中文字幕一区二区| 在线中文免费黄色| 狠狠久久综合丁香777米奇| 另类蜜桃刺激视频在线观看| 五月天色图婷婷亚洲| 日韩中文字幕在线网站| 福利小视频国产一区| 国产91在线播放精品| 久久综合中文字幕一区二区三区 | 免费麻豆国产一区二区三区| 厕所偷拍视频一区二区三区| 免费a级电影在线观看| 影音在线精品免费国产资源| 精品一级国产 av| 视频免费在线观看91| 欧美爱情动作片在线一区| 欧美日韩成人三级在线| 高清视频在线观看一区二区三区| 欧美熟妇精品在线观看 | 99re热在线精品视频9| 高清中文字幕乱码在线| 女人体内射精一区二区三区 | 精品人妻一区二区三区人妻视频| 国语黄色淫秽录像带| 少妇高潮喷水久久久久久桃花| 久久热最新视频在线观看| 欧美日韩亚洲大片在线| 91人妻九色大屁股| 中文字幕熟女人妻乳一区二区| 欧美aⅴ一区二区三区| sepapa自拍偷拍| 中文字幕一区二区三区中文字幕 | 欧美日韩成人三级在线| 色婷婷国产熟妇人妻露脸| 91精品一二三区在线观看 | 成人黄视频在线播放| 精品国产精品视频免费在线观看| 欧美日韩一区二区综合视频| 欧美日本一道本一区二区| av传媒高清影院免费| 91嫩草17c欧美国产| 国产成人av吴梦梦视频| 日韩av午夜免费| av成人教育在线播放| 91沈先生探花极品在线| 最新亚洲国产中文字幕av| 骚妻少妇一区二区| 9久热这里有国产精品| 天天操天天干天天妻| 国产剧情高清在线观看| 伊人久久婷婷色综合98网| 亚洲欧洲黄色图区| 欧美一区二区三区激情啪啪啪| 国产精品久久久久久久网站门| 国产高潮好爽受不了了视频 | 蜜臀av日韩特黄大片| 国产a级片免费在线观看| 婷婷激情五月天图片| 亚洲国产精品午夜av| 99久久久99久久91熟女| 香蕉在线蕉久在线| 日韩av电影在线观看的| 婷婷基地中文字幕| 日韩欧美 国产精品| 嫩草一区二区三区四区中文 | 午夜寻花美女在线| 2020日本中文字幕| 精品一区二区三区四区| 9久热这里有国产精品| 大香蕉大香蕉大香蕉大香蕉大| 精品人妻一区二区三区√ | 国产日韩欧美春色另类小说| 日韩av一区中文| 亚洲国产精品97久久宅男| 91国产视频网站在线观看| 国产丝袜香蕉在线观看| 免费av网站在线浏览| 久久人妻久久人妻一区| 黑人操日本女人电影| 免费av网站在线浏览| 久久久久久夜夜夜精品国产| 久久精品国产亚洲av久丨| 人妻精品少妇嫩草麻豆| 五月婷婷激情四射综合网| 国产欧美一二三区视频| 日韩精品刺激视频| 天天干天天草天天日天天天射伊人| 精品乱码一区二区三区四区| 自拍偷拍亚洲欧美另类| 久久久久久久久久久久久熟女a∨| av一级二级三级久久久| 精品一区二区三区四区| 日本中文国产字幕| 日韩欧美综合一区二区在线| 丰满大屁股熟妇猛交xxx| 国产成人一区二区三区在线视频| 国产一区二区不卡91| 亚洲制服欧美丝袜| 97cao瑟瑟在线观看| 精品视频在线观看一区二区97| 久久久精品欧美一区二区国产| 丰满大屁股熟妇猛交xxx| 国产成人精品久久久久久蜜臀 | 999精品插丰满少妇人妻| 秋霞在线观看色哟哟视频| 亚洲欧美一二三视频| 久久久免费精品少妇| 欧美一级黄片视频看看| 国产99久久久国产精品成人免费| 热久久免费频精品18| 婷婷激情五月天图片| 精品中文久久久久久| av日韩中文字幕人妻| 亚洲狠狠婷婷综合久久a| 日韩欧美久久免费观看| 日韩免费美女电影| 人妻啪啪视频免费看| 伊人久久中文字幕综合观看| 国产精品久久久久成人片| 久久五月婷婷综合视频| 国产成人av最新网址| 欧美aⅴ一区二区三区| 免费人妻一区二区三区免费视频| 天天射天天舔天天射| 国产99不卡免费在线观看| 日韩一区二区三区水蜜桃| 日本av都有哪些系列| 亚洲精品乱码97久久久久久| 国产精品综合手机在线| 2020日韩中文字幕| 在线观看色有小视频| 蜜臀av久久久久av蜜臀| 亚洲国产精品久久久久婷婷av| 亚洲熟妇av日韩熟妇在线| 久久久成人在线免费视频| 黑人操日本女人电影| 久久久久久久免费女人体| 在线不卡日韩视频播放| 97cao瑟瑟在线观看| 50岁老熟女一区二区三区| 久久久精品99国产国产精| 日韩美女主播人体视频自拍首页| 免费麻豆国产一区二区三区| 狠狠久久综合丁香777米奇| 久久精品一区二区三区人妻蜜桃| 思思久久国产精品视频| 人妻精品一区二区在线播放| 日本少妇人妻xxxx| 人妻夜夜爽天天爽麻豆| 2020中文字幕在线看电影| 超碰97在线观看国产| 999精品插丰满少妇人妻| 四虎网站免费av| 208精品福利导航| 精品国产乱码久久久人妻| 国产无av码在线观看| 青青草成人影院在线观看| 国内精品久久久久久久久久清纯 | 人人妻人人爱碰千| 99热2这里只有精品| 激情五月天狠婷婷| 日本熟妇乱子伦a片在线观看| 日韩av午夜精品| 蜜臀久久99精品久久久久久久久| 2020日本中文字幕| 色综合久久久久久久久| 中文字幕久久91| 亚洲欧洲色图动图| 午夜日韩麻豆福利| 久久行黑国产露脸精品| 天天干天天插天天操天天日| 日韩av中文字幕一区| 五月婷婷激情四射综合网| 日韩欧美一二三级| 97久久碰人妻一区二区三区四| 韩国女团午夜大尺度福利| 中文字幕亚洲欧美国产| 日韩精品综合免费视频| 免费中文字幕在线播放| av熟妇翔田千里俱乐部| 日本高清不卡视频在线播放| 人妻精品无码一区二区三区| 亚洲自拍偷拍 av| 久久亚洲AV成人无码| 久久这里只有精品久| 91天仙tv国产福利精品| 欧美日韩精品在线观看免费| 青青草成人影院在线观看| 91免费av在线观看| 日韩午夜激情福利免费| 婷婷免费精品视频在线| 欧美日韩国产综合aⅴ| 骚妻少妇一区二区| 亚州av一区二区三区.| 厕所偷拍视频一区二区三区| 成人av激情网一区二区三区| 青草青草视频免费2在线观看| 99精品视频69v精品视频| 91国产手机视频在线观看| 高清一区二区三区日本4| 丰满人妻av白石茉莉奈电影| 欧美日本一道本一区二区| 麻豆中文字幕av在线| 亚洲五月婷婷激情图片| 国产欧美日韩不卡在线观看| 成人黄色午夜污网站在线观看| 蜜桃视频在线观看一区精品 | 综合激情五月天久久| 少妇人妻给我内射视频| 青青草青青操在线播放| 久久久久久久久久久最新| 十八禁久久久久久久久久久久久久| 玖玖资源站中文字幕一区二区 | 日韩av福利大片在线观看| 欧美人妻激情中文视频| 成人黄色午夜污网站在线观看| 综合激情伊人久久| 亚洲国模在线视频| 中文字幕婷婷网站| 玖玖资源站中文字幕一区二区| 国产精品男人的天堂999| 久久亚洲精品日韩高清| 国产精品久久欠久久al换脸综合| 日韩毛片亚洲av| 思思久久国产精品视频| 精品国产久久久久99| 欧美人妻激情中文视频| 人妻丰满精品一区二区三区| 色婷婷综合免费在线视频| 蜜臀久久99精品久久久久久久久| 亚洲欧美av在线观看| 91天仙tv国产福利精品| 久久99久久com| 天天日天天干天天爱天天| 久久精品美国亚洲av伦理| 国产日韩欧美春色另类小说| 欧美日韩成人精品视频| 国产精品日韩欧美综合| 综合 另类 自拍| 人妻人人揉人人澡人人| 日韩成人av影视在线观看| 丰满的人妻一区七区| 国产五月天在线观看视频| 国产精品久久久久久久久粉嫩av| 亚洲欧洲色图动图| 97久久视频免费在线播放| 成人免费观看av毛片| 又粗又猛又爽黄老大爷视频| 99re6热在线视频免费观看| 日本二次元少女裸| 国产欧美日韩精品专区黑人| 国产美女深喉口爆吞精免费| 97色视频在线看视频| 国产亚洲精久久久久久无码色戒| 免费a级电影在线观看| 久久99精品国产91| 国产高潮国产高潮久久久久久91| 欧美va亚洲va精品| 先锋资源站中文字幕| 成人国产一区二区免费| 免费av网站在线浏览| 国产日韩一区二区三区啪啪啪| 国产剧情高清在线观看| 久久蜜桃视频亚洲精品| 欧美亚洲av日韩综合一区| 精品乱码一区二区三四五六区| 日韩欧美xxxx大片| 日韩美女主播人体视频自拍首页| 精品乱码久久久久久蜜臀| 欧美中文字幕在线观看视频| 日韩中文字幕理伦| 日本高清不卡视频在线播放| 欧美一级黄片视频看看| 亚洲欧美一二三视频| av在线免费播放成人| 成人免费观看av毛片| 日本老女人视频在线观看| 国产精品一区二区三区福利| 91人妻人人澡.人人精品| 精品久久久久久亚洲国产999| 国产欧美一区二区二区精品| 久久热最新视频在线观看| 高清一区二区日韩视频精品| 真实玩弄白嫩丰满人妻少妇三级| 久久精品国产91久久麻豆自制| 欧美中文字幕在线一区| 欧美中文字幕视频网| 安斋拉拉中文字幕在线| 国产美女深喉口爆吞精免费| 国产又粗又硬又长又爽视频| 天天干天天插天天操天天日| 欧美一区二区理论片在线观看 | 人妻有码中文字幕中文| 夜夜撸日日撸夜夜爽日日干| 综合久久综合久久综合久久| av岛国不卡在线观看| 97国产免费电影网| 久久精品视频在线国国| huangse网站在线观看| 午夜日韩麻豆福利| 日韩精品综合视频在线| 国产91熟女免费视频| 国产精品综合手机在线| 欧美一区二区三区成人久久片| 玖玖资源站中文字幕一区二区 | 亚洲综合色激情五月| 国产三级久久久999111| 最新亚洲国产中文字幕av| 午夜寻花美女在线| 久久精品一区二区三区人妻蜜桃| 88av亚洲精品日韩一区二区| 91人妻九色大屁股| 91偷拍老熟女露脸合集| 人妻精品少妇嫩草麻豆| 亚洲av电影在线一区二区| 欧美aⅴ一区二区三区| 日韩成人免费电影三区| 久久视频精彩在线观看| 国产网址手机上可以看的国产网站| 搡老熟女一区二区三区老熟女| 中文字幕熟女人妻在线观看| 黑人粗大精品一区二区| 国产69tv精品久久| 久久久久久久免费女人体| 成人国产一区二区免费| 大香蕉大香蕉大香蕉大香蕉大| 少妇高潮一区二区三区99欧美 | 人人妻人人澡人人爽国产一区 | 亚洲国模私拍视频| 国产精品99久久电影| 欧美日韩成人三级在线| 91人妻人人澡.人人精品| 国产美女深喉口爆吞精免费| 18禁成年av网站免费看| 日韩欧美激情入口| 青青青手机版视频在线看| 热热久久这里只有精品| 久久久亚洲熟妇熟女ⅹx| 色噜噜狠狠躁夜夜躁| 日韩av在线不卡网站| 国产精品久久久久久久漫画| 日韩成人av影视在线观看| 欧美区 日韩区 国产区| 208精品福利导航| 欧美日韩国产色图视频| 99精品视频在线看17| 精品一区二区三区蜜桃臀的优势| 999精品插丰满少妇人妻| 婷婷基地中文字幕| 亚洲情欲大片在线观看| 国产欧美一二三区视频| 一区二区 熟女人妻| 日韩欧美爱爱视频免费观看| 国产精品久久久久久xxx| 久久久久国产亚洲av麻豆| 欧美精品国产精品久久久| 大香蕉久草网一区二区三区| 久久亚洲熟妇中文字幕| 成人精品1024欧美日韩| 亚洲自拍偷拍色图区| 久久婷婷激情综合色综合俺也去| 欧美日韩久久久久久精品| 999精品插丰满少妇人妻| 亚洲制服欧美丝袜| 18禁成年av网站免费看| 日韩草比网站在线免费观看| 热香蕉和冷香蕉功效一样吗| 亚洲 免费 在线 观看| 天天操天天干天天色| 最新精品成人在线| 亚洲尺码和欧洲尺码av| 精品蜜臀久久久久抄底 | 之久精品一区二区| 安斋拉拉中文字幕在线| 精品国产久久久久蜜臀| 秋霞电影韩国一区二区二区三区 | 麻豆网站在线免费看| 日韩一级黄色大片免费观看| 色婷婷久久久swag精品| 日韩a v日日夜夜| www.199麻豆在线视频| 91精品欧美久久久久视频| 国产日韩av免费一区二区三区| av成人教育在线播放| 五月黄色激情视频| 欧美一区二区精品人妻免费视频 | 亚洲 自拍偷拍 欧美| 久久精品国产久精果冻传媒| 91精品欧美久久久久视频| 欧美日韩精品欧美日韩| 亚洲欧美日韩中出| av福利网站在线观看| 五月婷婷激情四射综合网| 我要看一级国产黄色绿像| 91麻豆免费国产在线| 99热这里只有的精品| 婷婷 少妇 av| 99久久窝窝午夜影视| 狠狠干中文字幕97视频| 狠狠久久综合丁香777米奇| 国产99不卡免费在线观看| 草裙成人精品一区二区三区| 在线国产小视频麻豆 | 在线免费观看日韩精品视频| 综合激情伊人久久| 欧美日韩精品一区电影| 亚洲天堂黄色在线| 最新亚洲国产中文字幕av| 国产成人精品久久久女| aaa久久久久久久久久网站| 日韩一级黄色大片免费观看| 日韩午夜精品啪啪啪| ass日本丰满熟妇pics| 亚洲成人av久久久久| 日韩不卡高清视频| 少妇激情视频一区二区| 日本黄色成年视频| 国产精品福利久久久久久久| 成人午夜激情福利片| 久久97久久免费视频| 亚洲成人久久久久| 99久久窝窝午夜影视| 亚洲情欲大片在线观看| 国产精品久久久久久久网站门| 欧美激情欧美情色成人在线| 欧美精品一区二区在线视频| 久久五月天天婷婷激情综合| 97精品久久人人爽人人爽| 18在线观看久久久麻豆| 色丁香婷婷综合久久| 91啪啪啪内射网站| 91欧美亚洲综合网| 青青草成人影院在线观看| 欧美最猛性亚洲精品推荐| 日本午夜在线免费观看| 1024欧美一区二区看片| 国产精品一区二区久久精品蜜臀| 精品久久久久久999| 丝袜日韩中文字幕| 国产+日本+欧美在线观看| 亚洲国产aⅴ精品一区二区欧美| 五月婷婷激情四射综合网| 日韩久久久三级电影| 少妇一区二区在线免费观看| 精品99国内中文字幕| 精品一区二区三区四区日产| 人妻啪啪视频免费看| 日韩成人免费电影三区| 久久爱免费视频16| 91精品久久久久久五月天| 91嫩草17c欧美国产| www.色av成人| 午夜日韩麻豆福利| 少妇一区二区在线免费观看| 久久精品国产91久久麻豆自制 | 人妻啪啪视频免费看| 日韩大全毛片免费观看视频| 久久久亚洲在线视频| 一本色道久久亚洲综合精品蜜桃| 99久久精品国产777| 亚洲制服高清中文字幕| 搡老熟女一区二区三区老熟女| 精品97人妻无码中文永久| 国产成人精品视频免费网站| 91精品一二三区在线观看| 国产人妻另类综合专区| 亚洲天堂黄色免费| 日韩av福利大片在线观看| 蜜桃黄色av网站免费播放| 日日碰狠狠躁久久躁一区二区| 精品久久中文字幕系列| 亚洲一区二区三二区厕所偷拍| 亚洲成人日韩丶av| 老熟女17页一91| 欧美日韩国产色图视频| 麻豆网站在线免费看| 久久久久久精品国产成人| 亚洲欧美一二三视频| 亚洲情色av网站| 午夜探花在线免费观看| 精品久久中文字幕系列| 国产欧美日韩制服丝袜在线| 欧美亚洲av日韩综合一区| 欧美肥臀精品一区二区三区| 精品人妻二区中文字幕| 婷婷在线综合观看视频| 亚洲一区二区三二区厕所偷拍| 68国产成人综合久久精品| 天天色天天日天天操| 亚洲伊人网在线观看| 亚洲欧洲久久精品| 色婷婷久久久swag精品| 精品中文久久久久久| 伊人久久中文字幕综合观看| 亚洲国产精品久久久久婷婷av| 99精品高清视频一区二区| 999热精品在线观看| 欧美熟女vides| 成人在线观看黄色片| 亚洲天堂黄色在线| 精品久久精品久久久久| 日韩中文字幕在线综合网| 午夜精品福利小视频| 亚洲欧美日韩偷拍综合| 日韩av中文网址| 中文字幕的不卡人妻| youwu视频在线| 日韩av在线天堂| 欧美一区二区三区激情啪啪啪| 精品视频在线观看一区二区97| 99爱99久久久久久久久久| 91天仙tv国产福利精品| 亚洲国产精品国自产拍av麻豆| 99精品视频69v精品视频| 亚洲av不卡码在线看| 激情黄色开心五月天| 欧美日韩在线卡一卡二卡三| 亚洲图色91东京热| 久久久精品99国产国产精| 国产一级av国产免费| 日韩日韩av在线| 久久久96精品久久久| 三级亚洲天堂亚洲天堂| 亚洲欧美日韩偷拍综合| 久久精品国产亚洲av久丨| 欧美亚洲av日韩综合一区| 亚洲日韩视频高清在线观看| 日韩国产精品电影网| 污视频在线观看91| 麻豆在线视频看片免费| 午夜精品久久久久久久久二区三区 | 99久久国语露脸精彩对白| 婷婷亚洲免费基地| 玖玖玖玖日在线视频| av福利网站在线观看| 少妇人妻视频在线观看| 明天我们好好过高清免费| 久久综合久久综合久久色| 日韩a大片在线观看| 91精品久久久久久久久不卡网站| 精品国产久久久久蜜臀| 亚洲一级av大片| 激情四射五月开心六月婷婷| 9久热这里有国产精品| 无码人妻精品一区二区三区久久| 久久精品色婷婷国产网站| 欧美日韩少妇一二三| 成人黄片av在线播放| 日本久久久大片中文字幕 | 91丝袜放荡丝袜脚交| 中文字幕亚洲专区欧美| 美女差点操死在线观看| 91超碰熟女在线97| 久久国产精品——国产精品| 日韩中文字幕有码人妻在线| 青青青青青欧美在线视频观看| 亚洲av微乳在线| 国产91熟女免费视频| 婷婷激情免费视频| 中文字幕+人妻熟女| 久久久久久久久久无吗| 久久五月天天婷婷激情综合| 色婷婷中文字幕基地| 国产精品久久久久久吹吹潮| 精品久久精品久久久久| 人妻精品少妇嫩草麻豆| 亚洲 自拍偷拍 欧美| 一级久久久久久久18|