青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

JavaScript面向對象的支持(3)

Posted on 2009-09-15 09:26 S.l.e!ep.¢% 閱讀(359) 評論(0)  編輯 收藏 引用 所屬分類: HTML
JavaScript面向對象的支持(3)
2008-05-25 22:56
然而再接下來,我們發現MyObject2()的實例obj2的constructor仍然指向function MyObject()。
盡管這很說不通,然而現實的確如此?!@到底是為什么呢?

事實上,僅下面的代碼:
--------
function MyObject2() {
}

obj2 = new MyObject2();
document.writeln(MyObject2.prototype.constructor === MyObject2);
--------
構造的obj2.constructor將正確的指向function MyObject2()。事實上,我們也會注意到這
種情況下,MyObject2的原型屬性的constructor也正確的指向該函數。然而,由于JavaScript
要求指定prototype對象來構造原型鏈:
--------
function MyObject2() {
}
MyObject2.prototype = new MyObject();

obj2 = new MyObject2();
--------
這時,再訪問obj2,將會得到新的原型(也就是MyObject2.prototype)的constructor屬性。
因此,一切很明了:原型的屬性影響到構造過程對對象的constructor的初始設定。

作為一種補充的解決問題的手段,JavaScript開發規范中說“need to remember to reset
the constructor property',要求用戶自行設定該屬性。

所以你會看到更規范的JavaScript代碼要求這樣書寫:
//---------------------------------------------------------
// 維護constructor屬性的規范代碼
//---------------------------------------------------------
function MyObject2() {
}
MyObject2.prototype = new MyObject();
MyObject2.prototype.constructor = MyObject2;

obj2 = new MyObject2();

更外一種解決問題的方法,是在function MyObject()中去重置該值。當然,這樣會使
得執行效率稍低一點點:
//---------------------------------------------------------
// 維護constructor屬性的第二種方式
//---------------------------------------------------------
function MyObject2() {
?? this.constructor = arguments.callee;
?? // or, this.constructor = MyObject2;

?? // ...
}
MyObject2.prototype = new MyObject();

obj2 = new MyObject2();

5). 析構問題
------
JavaScript中沒有析構函數,但卻有“對象析構”的問題。也就是說,盡管我們不
知道一個對象什么時候會被析構,也不能截獲它的析構過程并處理一些事務。然而,
在一些不多見的時候,我們會遇到“要求一個對象立即析構”的問題。

問題大多數的時候出現在對ActiveX Object的處理上。因為我們可能在JavaScript
里創建了一個ActiveX Object,在做完一些處理之后,我們又需要再創建一個。而
如果原來的對象供應者(Server)不允許創建多個實例,那么我們就需要在JavaScript
中確保先前的實例是已經被釋放過了。接下來,即使Server允許創建多個實例,而
在多個實例間允許共享數據(例如OS的授權,或者資源、文件的鎖),那么我們在新
實例中的操作就可能會出問題。

可能還是有人不明白我們在說什么,那么我就舉一個例子:如果創建一個Excel對象,
打開文件A,然后我們save它,然后關閉這個實例。然后我們再創建Excel對象并打開
同一文件。——注意這時JavaScript可能還沒有來得及析構前一個對象?!@時我們
再想Save這個文件,就發現失敗了。下面的代碼示例這種情況:
//---------------------------------------------------------
// JavaScript中的析構問題(ActiveX Object示例)
//---------------------------------------------------------
<script>
var strSaveLocation = 'file:///E:/1.xls'

function createXLS() {
?? var excel = new ActiveXObject("Excel.Application");
?? var wk = excel.Workbooks.Add();
?? wk.SaveAs(strSaveLocation);
?? wk.Saved = true;

?? excel.Quit();
}

function writeXLS() {
?? var excel = new ActiveXObject("Excel.Application");
?? var wk = excel.Workbooks.Open(strSaveLocation);
?? var sheet = wk.Worksheets(1);
?? sheet.Cells(1, 1).Value = '測試字符串';
?? wk.SaveAs(strSaveLocation);
?? wk.Saved = true;

?? excel.Quit();
}
</script>
<body>
?? <button onclick="createXLS()">創建</button>
?? <button onclick="writeXLS()">重寫</button>
</body>

在這個例子中,在本地文件操作時并不會出現異常。——最多只是有一些內存垃
圾而已。然而,如果strSaveLocation是一個遠程的URL,這時本地將會保存一個
文件存取權限的憑證,而且同時只能一個(遠程的)實例來開啟該excel文檔并存
儲。于是如果反復點擊"重寫"按鈕,就會出現異常。

——注意,這是在SPS中操作共享文件時的一個實例的簡化代碼。因此,它并非
“學術的”無聊討論,而且工程中的實際問題。

解決這個問題的方法很復雜。它涉及到兩個問題:
?? - 本地憑證的釋放
?? - ActiveX Object實例的釋放

下面我們先從JavaScript中對象的“失效”問題說起。簡單的說:
?? - 一個對象在其生存的上下文環境之外,即會失效。
?? - 一個全局的對象在沒有被執用(引用)的情況下,即會失效。

例如:
//---------------------------------------------------------
// JavaScript對象何時失效
//---------------------------------------------------------
function testObject() {
?? var _obj1 = new Object();
}

function testObject2() {
?? var _obj2 = new Object();
?? return _obj2;
}

// 示例1
testObject();

// 示例2
testObject2()

// 示例3
var obj3 = testObject2();
obj3 = null;

// 示例4
var obj4 = testObject2();
var arr = [obj4];
obj3 = null;
arr = [];

在這四個示例中:
?? - “示例1”在函數testObject()中構造了_obj1,但是在函數退出時,
???? 它就已經離開了函數的上下文環境,因此_obj1失效了;
?? - “示例2”中,testObject2()中也構造了一個對象_obj2并傳出,因
???? 此對象有了“函數外”的上下文環境(和生存周期),然而由于函數
???? 的返回值沒有被其它變量“持有”,因此_obj2也立即失效了;
?? - “示例3”中,testObject2()構造的_obj2被外部的變量obj3持用了,
???? 這時,直到“obj3=null”這行代碼生效時,_obj2才會因為引用關系
???? 消失而失效。
?? - 與示例3相同的原因,“示例4”中的_obj2會在“arr=[]”這行代碼
???? 之后才會失效。

但是,對象的“失效”并不等會“釋放”。在JavaScript運行環境的內部,沒
有任何方式來確切地告訴用戶“對象什么時候會釋放”。這依賴于JavaScript
的內存回收機制?!@種策略與.NET中的回收機制是類同的。

在前面的Excel操作示例代碼中,對象的所有者,也就是"EXCEL.EXE"這個進程
只能在“ActiveX Object實例的釋放”之后才會發生。而文件的鎖,以及操作
系統的權限憑證是與進程相關的。因此如果對象僅是“失效”而不是“釋放”,
那么其它進程處理文件和引用操作系統的權限憑據時就會出問題。

——有些人說這是JavaScript或者COM機制的BUG。其實不是,這是OS、IE
和JavaScript之間的一種復雜關系所導致的,而非獨立的問題。

Microsoft公開了解決這種問題的策略:主動調用內存回收過程。

在(微軟的)JScript中提供了一個CollectGarbage()過程(通常簡稱GC過程),
GC過程用于清理當前IE中的“失效的對象失例”,也就是調用對象的析構過程。

在上例中調用GC過程的代碼是:
//---------------------------------------------------------
// 處理ActiveX Object時,GC過程的標準調用方式
//---------------------------------------------------------
function writeXLS() {
?? //(略...)

?? excel.Quit();
?? excel = null;
?? setTimeout(CollectGarbage, 1);
}

第一行代碼調用excel.Quit()方法來使得excel進程中止并退出,這時由于JavaScript
環境執有excel對象實例,因此excel進程并不實際中止。

第二行代碼使excel為null,以清除對象引用,從而使對象“失效”。然而由于
對象仍舊在函數上下文環境中,因此如果直接調用GC過程,對象仍然不會被清理。

第三行代碼使用setTimeout()來調用CollectGarbage函數,時間間隔設為'1',只
是使得GC過程發生在writeXLS()函數執行完之后。這樣excel對象就滿足了“能被
GC清理”的兩個條件:沒有引用和離開上下文環境。

GC過程的使用,在使用了ActiveX Object的JS環境中很有效。一些潛在的ActiveX
Object包括XML、VML、OWC(Office Web Componet)、flash,甚至包括在JS中的VBArray。
從這一點來看,ajax架構由于采用了XMLHTTP,并且同時要滿足“不切換頁面”的
特性,因此在適當的時候主動調用GC過程,會得到更好的效率用UI體驗。

事實上,即使使用GC過程,前面提到的excel問題仍然不會被完全解決。因為IE還
緩存了權限憑據。使頁的權限憑據被更新的唯一方法,只能是“切換到新的頁面”,
因此事實上在前面提到的那個SPS項目中,我采用的方法并不是GC,而是下面這一
段代碼:
//---------------------------------------------------------
// 處理ActiveX Object時采用的頁面切換代碼
//---------------------------------------------------------
function writeXLS() {
?? //(略...)

?? excel.Quit();
?? excel = null;

?? // 下面代碼用于解決IE call Excel的一個BUG, MSDN中提供的方法:
?? //??? setTimeout(CollectGarbage, 1);
?? // 由于不能清除(或同步)網頁的受信任狀態, 所以將導致SaveAs()等方法在
?? // 下次調用時無效.
?? location.reload();
}

最后之最后,關于GC的一個補充說明:在IE窗體被最小化時,IE將會主動調用一次
CollectGarbage()函數。這使得IE窗口在最小化之后,內存占用會有明顯改善。

八、JavaScript面向對象的支持
~~~~~~~~~~~~~~~~~~
(續)

4. 實例和實例引用
--------
在.NET Framework對CTS(Common Type System)約定“一切都是對象”,并分為“值類型”和“引用類型”兩種。其中“值類型”的對象在轉換成“引用類型”數據的過程中,需要進行一個“裝箱”和“拆箱”的過程。

在JavaScript也有同樣的問題。我們看到的typeof關鍵字,返回以下六種數據類型:
"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。

我們也發現JavaScript的對象系統中,有String、Number、Function、Boolean這四種對象構造器。那么,我們的問題是:如果有一個數字A,typeof(A)的結果,到底會是'number'呢,還是一個構造器指向function Number()的對象呢?

//---------------------------------------------------------
// 關于JavaScript的類型的測試代碼
//---------------------------------------------------------
function getTypeInfo(V) {
?? return (typeof V == 'object' ??? 'Object, construct by '+V.constructor
??? : 'Value, type of '+typeof V);
}

var A1 = 100;
var A2 = new Number(100);

document.writeln('A1 is ', getTypeInfo(A1), '<BR>');
document.writeln('A2 is ', getTypeInfo(A2), '<BR>');
document.writeln([A1.constructor === A2.constructor, A2.constructor === Number]);

測試代碼的執行結果如下:
-----------
A1 is Value, type of number
A2 is Object, construct by function Number() { [native code] }
true,true
-----------

我們注意到,A1和A2的構造器都指向Number。這意味著通過constructor屬性來識別對象,(有時)比typeof更加有效。因為“值類型數據”A1作為一個對象來看待時,與A2有完全相同的特性。

——除了與實例引用有關的問題。

參考JScript手冊,我們對其它基礎類型和構造器做相同考察,可以發現:
?? - 基礎類型中的undefined、number、boolean和string,是“值類型”變量
?? - 基礎類型中的array、function和object,是“引用類型”變量
?? - 使用new()方法構造出對象,是“引用類型”變量

下面的代碼說明“值類型”與“引用類型”之間的區別:
//---------------------------------------------------------
// 關于JavaScript類型系統中的值/引用問題
//---------------------------------------------------------
var str1 = 'abcdefgh', str2 = 'abcdefgh';
var obj1 = new String('abcdefgh'), obj2 = new String('abcdefgh');

document.writeln([str1==str2, str1===str2], '<br>');
document.writeln([obj1==obj2, obj1===obj2]);

測試代碼的執行結果如下:
-----------
true, true
false, false
-----------

我們看到,無論是等值運算(==),還是全等運算(===),對“對象”和“值”的理解都是不一樣的。

更進一步的理解這種現象,我們知道:
?? - 運算結果為值類型,或變量為值類型時,等值(或全等)比較可以得到預想結果
?? - (即使包含相同的數據,)不同的對象實例之間是不等值(或全等)的
?? - 同一個對象的不同引用之間,是等值(==)且全等(===)的

但對于String類型,有一點補充:根據JScript的描述,兩個字符串比較時,只要有一個是值類型,則按值比較。這意味著在上面的例子中,代碼“str1==obj1”會得到結果true。而全等(===)運算需要檢測變量類型的一致性,因此“str1===obj1”的結果返回false。

JavaScript中的函數參數總是傳入值參,引用類型(的實例)是作為指針值傳入的。因此函數可以隨意重寫入口變量,而不用擔心外部變量被修改。但是,需要留意傳入的引用類型的變量,因為對它方法調用和屬性讀寫可能會影響到實例本身。——但,也可以通過引用類型的參數來傳出數據。

最后補充說明一下,值類型比較會逐字節檢測對象實例中的數據,效率低但準確性高;而引用類型只檢測實例指針和數據類型,因此效率高而準確性低。如果你需要檢測兩個引用類型是否真的包含相同的數據,可能你需要嘗試把它轉換成“字符串值”再來比較。

6. 函數的上下文環境
--------
只要寫過代碼,你應該知道變量是有“全局變量”和“局部變量”之分的。絕大多數的
JavaScript程序員也知道下面這些概念:
//---------------------------------------------------------
// JavaScript中的全局變量與局部變量
//---------------------------------------------------------
var v1 = '全局變量-1';
v2 = '全局變量-2';

function foo() {
?? v3 = '全局變量-3';

?? var v4 = '只有在函數內部并使用var定義的,才是局部變量';
}

按照通常對語言的理解來說,不同的代碼調用函數,都會擁有一套獨立的局部變量。
因此下面這段代碼很容易理解:
//---------------------------------------------------------
// JavaScript的局部變量
//---------------------------------------------------------
function MyObject() {
?? var o = new Object;

?? this.getValue = function() {
???? return o;
?? }
}

var obj1 = new MyObject();
var obj2 = new MyObject();
document.writeln(obj1.getValue() == obj2.getValue());

結果顯示false,表明不同(實例的方法)調用返回的局部變量“obj1/obj2”是不相同。

變量的局部、全局特性與OOP的封裝性中的“私有(private)”、“公開(public)”具有類同性。因此絕大多數資料總是以下面的方式來說明JavaScript的面向對象系統中的“封裝權限級別”問題:
//---------------------------------------------------------
// JavaScript中OOP封裝性
//---------------------------------------------------------
function MyObject() {
?? // 1. 私有成員和方法
?? var private_prop = 0;
?? var private_method_1 = function() {
???? // ...
???? return 1
?? }
?? function private_method_2() {
???? // ...
???? return 1
?? }

?? // 2. 特權方法
?? this.privileged_method = function () {
???? private_prop++;
???? return private_prop + private_method_1() + private_method_2();
?? }

?? // 3. 公開成員和方法
?? this.public_prop_1 = '';
?? this.public_method_1 = function () {
???? // ...
?? }
}

// 4. 公開成員和方法(2)
MyObject.prototype.public_prop_1 = '';
MyObject.prototype.public_method_1 = function () {
?? // ...
}

var obj1 = new MyObject();
var obj2 = new MyObject();

document.writeln(obj1.privileged_method(), '<br>');
document.writeln(obj2.privileged_method());

在這里,“私有(private)”表明只有在(構造)函數內部可訪問,而“特權(privileged)”是特指一種存取“私有域”的“公開(public)”方法?!肮_(public)”表明在(構造)函數外可以調用和存取。

除了上述的封裝權限之外,一些文檔還介紹了其它兩種相關的概念:
?? - 原型屬性:Classname.prototype.propertyName = someValue
?? - (類)靜態屬性:Classname.propertyName = someValue

然而,從面向對象的角度上來講,上面這些概念都很難自圓其說:JavaScript究竟是為何、以及如何劃分出這些封裝權限和概念來的呢?

——因為我們必須注意到下面這個例子所帶來的問題:
//---------------------------------------------------------
// JavaScript中的局部變量
//---------------------------------------------------------
function MyFoo() {
?? var i;

?? MyFoo.setValue = function (v) {
????? i = v;
?? }
?? MyFoo.getValue = function () {
????? return i;
?? }
}
MyFoo();

var obj1 = new Object();
var obj2 = new Object();

// 測試一
MyFoo.setValue.call(obj1, 'obj1');
document.writeln(MyFoo.getValue.call(obj1), '<BR>');

// 測試二
MyFoo.setValue.call(obj2, 'obj2');
document.writeln(MyFoo.getValue.call(obj2));
document.writeln(MyFoo.getValue.call(obj1));
document.writeln(MyFoo.getValue());

在這個測試代碼中,obj1/obj2都是Object()實例。我們使用function.call()的方式來調用setValue/getValue,使得在MyFoo()調用的過程中替換this為obj1/obj2實例。

然而我們發現“測試二”完成之后,obj2、obj1以及function MyFoo()所持有的局部變量都返回了“obj2”?!@表明三個函數使用了同一個局部變量。

由此可見,JavaScript在處理局部變量時,對“普通函數”與“構造器”是分別對待的。這種處理策略在一些JavaScript相關的資料中被解釋作“面向對象中的私有域”問題。而事實上,我更愿意從源代碼一級來告訴你真相:這是對象的上下文環境的問題。——只不過從表面看去,“上下文環境”的問題被轉嫁到對象的封裝性問題上了。

(在閱讀下面的文字之前,)先做一個概念性的說明:
?? - 在普通函數中,上下文環境被window對象所持有
- 在“構造器和對象方法”中,上下文環境被對象實例所持有

在JavaScript的實現代碼中,每次創建一個對象,解釋器將為對象創建一個上下文環境鏈,用于存放對象在進入“構造器和對象方法”時對function()內部數據的一個備份。JavaScript保證這個對象在以后再進入“構造器和對象方法”內部時,總是持有該上下文環境,和一個與之相關的this對象。由于對象可能有多個方法,且每個方法可能又存在多層嵌套函數,因此這事實上構成了一個上下文環境的樹型鏈表結構。而在構造器和對象方法之外,JavaScript不提供任何訪問(該構造器和對象方法的)上下文環境的方法。

簡而言之:
?? - 上下文環境與對象實例調用“構造器和對象方法”時相關,而與(普通)函數無關
?? - 上下文環境記錄一個對象在“構造函數和對象方法”內部的私有數據
?? - 上下文環境采用鏈式結構,以記錄多層的嵌套函數中的上下文

由于上下文環境只與構造函數及其內部的嵌套函數有關,重新閱讀前面的代碼:
//---------------------------------------------------------
// JavaScript中的局部變量
//---------------------------------------------------------
function MyFoo() {
?? var i;

?? MyFoo.setValue = function (v) {
????? i = v;
?? }
?? MyFoo.getValue = function () {
????? return i;
?? }
}
MyFoo();

var obj1 = new Object();
MyFoo.setValue.call(obj1, 'obj1');

我們發現setValue()的確可以訪問到位于MyFoo()函數內部的“局部變量i”,但是由于setValue()方法的執有者是MyFoo對象(記住函數也是對象),因此MyFoo對象擁有MyFoo()函數的唯一一份“上下文環境”。

接下來MyFoo.setValue.call()調用雖然為setValue()傳入了新的this對象,但實際上擁有“上下文環境”的仍舊是MyFoo對象。因此我們看到無論創建多少個obj1/obj2,最終操作的都是同一個私有變量i。

全局函數/變量的“上下文環境”持有者為window,因此下面的代碼說明了“為什么全局變量能被任意的對象和函數訪問”:
//---------------------------------------------------------
// 全局函數的上下文
//---------------------------------------------------------
/*
function Window() {
*/
?? var global_i = 0;
?? var global_j = 1;

?? function foo_0() {
?? }

?? function foo_1() {
?? }
/*
}

window = new Window();
*/

因此我們可以看到foo_0()與foo_1()能同時訪問global_i和global_j。接下來的推論是,上下文環境決定了變量的“全局”與“私有”。而不是反過來通過變量的私有與全局來討論上下文環境問題。

更進一步的推論是:JavaScript中的全局變量與函數,本質上是window對象的私有變量與方法。而這個上下文環境塊,位于所有(window對象內部的)對象實例的上下文環境鏈表的頂端,因此都可能訪問到。

用“上下文環境”的理論,你可以順利地解釋在本小節中,有關變量的“全局/局部”作用域的問題,以及有關對象方法的封裝權限問題。事實上,在實現JavaScript的C源代碼中,這個“上下文環境”被叫做“JSContext”,并作為函數/方法的第一個參數傳入?!绻阌信d趣,你可以從源代碼中證實本小節所述的理論。

另外,《JavaScript權威指南》這本書中第4.7節也講述了這個問題,但被叫做“變量的作用域”。然而重要的是,這本書把問題講反了?!髡咴噲D用“全局、局部的作用域”,來解釋產生這種現象的“上下文環境”的問題。因此這個小節顯得凌亂而且難以自圓其說。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美亚洲视频在线看网址| 亚洲国产欧美日韩另类综合| 欧美成人午夜激情视频| 国产一区二区三区在线播放免费观看 | 欧美精品麻豆| 亚洲欧美影音先锋| 久久国产精品免费一区| 国语精品中文字幕| 欧美日韩第一页| 亚洲免费在线视频| 欧美成人dvd在线视频| 一本色道**综合亚洲精品蜜桃冫 | 久久久亚洲高清| 亚洲欧洲在线免费| 在线视频精品一区| 免费观看亚洲视频大全| 亚洲图片欧美一区| 欧美大片免费| 久久久精品日韩| 欧美一区二区在线看| 亚洲片国产一区一级在线观看| 国产精品免费一区二区三区观看| 久久综合激情| 羞羞视频在线观看欧美| 99国产精品| 亚洲国产精品一区制服丝袜 | 亚洲国产精品999| 欧美综合第一页| 亚洲在线观看| 中文亚洲字幕| 亚洲网站视频| 一区二区高清视频| 欧美视频中文字幕在线| 日韩午夜在线电影| 一本色道久久综合亚洲精品按摩| 欧美激情性爽国产精品17p| 欧美成年人网| 欧美成人激情视频| 久久免费高清| 欧美不卡视频一区| 免费亚洲一区二区| 毛片一区二区三区| 欧美18av| 亚洲欧洲在线看| 国产精品免费小视频| 女生裸体视频一区二区三区| 欧美中文在线观看| 性伦欧美刺激片在线观看| 亚洲图片欧美午夜| 午夜视频一区在线观看| 99国产精品久久久久老师| 国产精品区一区二区三区| 久久婷婷久久| 欧美一区二区私人影院日本 | 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲欧美日韩在线一区| 亚洲欧美日韩另类| 久久久久免费观看| 老牛国产精品一区的观看方式| 亚欧成人在线| 免费在线观看成人av| 91久久极品少妇xxxxⅹ软件| 日韩五码在线| 久久福利一区| 欧美精品手机在线| 国产精品久久毛片a| 精品成人在线视频| 亚洲午夜一区二区三区| 久久精品夜色噜噜亚洲a∨| 亚洲电影在线| 女女同性精品视频| 久久久午夜视频| 日韩亚洲视频在线| 欧美在线观看视频在线| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美在线视频观看| 欧美高潮视频| 国产一区二区三区最好精华液| 91久久嫩草影院一区二区| 亚洲欧美综合v| 欧美激情亚洲激情| 欧美主播一区二区三区| 欧美天堂在线观看| 国产精品美女久久| 欧美黄色aa电影| 国产有码在线一区二区视频| 野花国产精品入口| 久久永久免费| 久久天天躁狠狠躁夜夜av| 亚洲理伦电影| 久久久久久9| 在线中文字幕一区| 欧美人牲a欧美精品| 亚洲片区在线| 欧美88av| 久久蜜桃精品| 国产一区美女| 亚洲精品1区2区| 一区二区三区我不卡| 久久se精品一区精品二区| 日韩系列在线| 欧美日韩免费高清| 9i看片成人免费高清| 欧美激情视频在线免费观看 欧美视频免费一 | 亚洲国产精品久久| 99re66热这里只有精品3直播| 久久精品视频在线看| 亚洲一区久久| 国产精品人人做人人爽人人添| 99国产精品自拍| 亚洲免费播放| 亚洲午夜视频在线| 亚洲欧洲日产国产网站| 久久成人免费| 亚洲欧美不卡| 欧美性片在线观看| 一本不卡影院| 亚洲日本在线观看| 欧美黄色免费| 日韩一级二级三级| 99日韩精品| 欧美在线关看| 国产麻豆精品久久一二三| 国产一区二区三区观看| 久久久精品国产99久久精品芒果| 亚洲人成欧美中文字幕| 欧美日本久久| 欧美一区网站| 久久亚洲国产成人| 国产无一区二区| 久久精品91| 亚洲日本国产| 欧美在线啊v一区| 亚洲欧美日韩一区二区三区在线| 欧美成人在线免费观看| 老司机免费视频一区二区| 国产欧美一区二区精品秋霞影院| 中文网丁香综合网| 亚洲欧美综合| 国产精品v欧美精品v日韩| 久久午夜羞羞影院免费观看| 亚洲欧美日韩爽爽影院| 欧美三级黄美女| 日韩一区二区精品| 在线亚洲激情| 欧美视频在线观看一区| 一本久久综合亚洲鲁鲁五月天| 亚洲在线国产日韩欧美| 国产精品久久久久一区二区| 在线视频精品一区| 久久一综合视频| 亚洲欧美日韩中文视频| 国产精品久久久一本精品| 午夜精品久久久久久久99热浪潮 | 亚洲一区在线看| 国产精品人成在线观看免费| 午夜亚洲伦理| 欧美高清视频| 一区二区三区四区五区精品| 国产精品女主播一区二区三区| 欧美亚洲自偷自偷| 欧美寡妇偷汉性猛交| 一本到高清视频免费精品| 国产精品拍天天在线| 久久精品国产91精品亚洲| 亚洲国产视频直播| 亚洲一区二区精品| 国产亚洲免费的视频看| 免费不卡在线观看| 日韩视频免费| 久久亚洲一区二区| 日韩一区二区免费高清| 国产精品一区二区视频| 麻豆精品网站| 亚洲欧美不卡| 亚洲激情电影中文字幕| 性欧美大战久久久久久久免费观看 | 99精品欧美| 国内精品**久久毛片app| 欧美激情精品久久久久久| 亚洲淫性视频| 亚洲欧洲三级| 免费美女久久99| 久久国产精品亚洲va麻豆| 99re6这里只有精品视频在线观看| 国产欧美va欧美va香蕉在| 欧美极品在线播放| 久久久久国产精品人| 亚洲午夜视频在线观看| 亚洲国产日韩欧美在线99| 久久亚洲私人国产精品va| 香蕉久久a毛片| 亚洲视频网在线直播| 最新国产成人在线观看| 黄色成人在线观看| 国产精品自在欧美一区| 欧美色精品天天在线观看视频 | 亚洲乱码国产乱码精品精| 久久视频一区| 久久精品av麻豆的观看方式 |