亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

學(xué)習(xí)Javascript閉包(Closure)

系統(tǒng) 3037 0

包(closure)是Javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包實(shí)現(xiàn)。

下面就是我的學(xué)習(xí)筆記,對(duì)于Javascript初學(xué)者應(yīng)該是很有用的。

一、變量的作用域

要理解閉包,首先必須理解Javascript特殊的變量作用域。

變量的作用域無(wú)非就是兩種:全局變量和局部變量。

Javascript語(yǔ)言的特殊之處,就在于函數(shù)內(nèi)部可以直接讀取全局變量。

  var n=999;

  function f1(){
    alert(n);
  }

  f1(); // 999

另一方面,在函數(shù)外部自然無(wú)法讀取函數(shù)內(nèi)的局部變量。

  function f1(){
    var n=999;
  }

  alert(n); // error

這里有一個(gè)地方需要注意,函數(shù)內(nèi)部聲明變量的時(shí)候,一定要使用var命令。如果不用的話,你實(shí)際上聲明了一個(gè)全局變量!

  function f1(){
    n=999;
  }

  f1();

  alert(n); // 999

二、如何從外部讀取局部變量?

出于種種原因,我們有時(shí)候需要得到函數(shù)內(nèi)的局部變量。但是,前面已經(jīng)說(shuō)過(guò)了,正常情況下,這是辦不到的,只有通過(guò)變通方法才能實(shí)現(xiàn)。

那就是在函數(shù)的內(nèi)部,再定義一個(gè)函數(shù)。

  function f1(){

    var n=999;

    function f2(){
      alert(n); // 999
    }

  }

在上面的代碼中,函數(shù)f2就被包括在函數(shù)f1內(nèi)部,這時(shí)f1內(nèi)部的所有局部變量,對(duì)f2都是可見的。但是反過(guò)來(lái)就不行,f2內(nèi)部的局部變量,對(duì)f1就是不可見的。這就是Javascript語(yǔ)言特有的"鏈?zhǔn)阶饔糜?結(jié)構(gòu)(chain scope),子對(duì)象會(huì)一級(jí)一級(jí)地向上尋找所有父對(duì)象的變量。所以,父對(duì)象的所有變量,對(duì)子對(duì)象都是可見的,反之則不成立。

既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,我們不就可以在f1外部讀取它的內(nèi)部變量了嗎!

  function f1(){

    var n=999;

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

三、閉包的概念

上一節(jié)代碼中的f2函數(shù),就是閉包。

各種專業(yè)文獻(xiàn)上的"閉包"(closure)定義非常抽象,很難看懂。我的理解是,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。

由于在Javascript語(yǔ)言中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,因此可以把閉包簡(jiǎn)單理解成"定義在一個(gè)函數(shù)內(nèi)部的函數(shù)"。

所以,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來(lái)的一座橋梁。

四、閉包的用途

閉包可以用在許多地方。它的最大用處有兩個(gè),一個(gè)是前面提到的可以讀取函數(shù)內(nèi)部的變量,另一個(gè)就是讓這些變量的值始終保持在內(nèi)存中。

怎么來(lái)理解這句話呢?請(qǐng)看下面的代碼。

  function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

在這段代碼中,result實(shí)際上就是閉包f2函數(shù)。它一共運(yùn)行了兩次,第一次的值是999,第二次的值是1000。這證明了,函數(shù)f1中的局部變量n一直保存在內(nèi)存中,并沒有在f1調(diào)用后被自動(dòng)清除。

為什么會(huì)這樣呢?原因就在于f1是f2的父函數(shù),而f2被賦給了一個(gè)全局變量,這導(dǎo)致f2始終在內(nèi)存中,而f2的存在依賴于f1,因此f1也始終在內(nèi)存中,不會(huì)在調(diào)用結(jié)束后,被垃圾回收機(jī)制(garbage collection)回收。

這段代碼中另一個(gè)值得注意的地方,就是"nAdd=function(){n+=1}"這一行,首先在nAdd前面沒有使用var關(guān)鍵字,因此nAdd是一個(gè)全局變量,而不是局部變量。其次,nAdd的值是一個(gè)匿名函數(shù)(anonymous function),而這個(gè)匿名函數(shù)本身也是一個(gè)閉包,所以nAdd相當(dāng)于是一個(gè)setter,可以在函數(shù)外部對(duì)函數(shù)內(nèi)部的局部變量進(jìn)行操作。

五、使用閉包的注意點(diǎn)

1)由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。

2)閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

六、思考題

如果你能理解下面兩段代碼的運(yùn)行結(jié)果,應(yīng)該就算理解閉包的運(yùn)行機(jī)制了。

代碼片段一。

  var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      return function(){
        return this.name;
      };

    }

  };

  alert(object.getNameFunc()());


代碼片段二。

  var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };

    }

  };

  alert(object.getNameFunc()());

(完)

<script src="/newwindow.js" type="text/javascript"></script>

相關(guān)文章

功能鏈接

留言(53條)

講的很清楚明了,連我都懂了,要是我們大學(xué)時(shí)的老師也能這么講課。。。他們只會(huì)放幻燈片

這里有個(gè) PPT 用于說(shuō)明 JS 閉包,說(shuō)明得很透徹: http://www.gracecode.com/archives/2385/

呵呵,可以作為面試題了!

閉包個(gè)人感覺是一種描述函數(shù)內(nèi)部的數(shù)據(jù)結(jié)構(gòu),來(lái)描述函數(shù)的運(yùn)行上下文.Javascript編程精粹 這本書算是講的比較好一點(diǎn).

類是有行為的數(shù)據(jù),閉包是有數(shù)據(jù)的行為。

阮兄:
有點(diǎn)疑問(wèn):
function f1(){

    n=999;

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999
可以寫成如下的不也一樣么?

function f1(){

    n=999;

    return n;

  }
var result=f1();
alert(result);

@tt 實(shí)際上后種方法每次調(diào)用 f1 時(shí),都會(huì)聲明 n = 999,而且 n 無(wú)法保留狀態(tài)值(嚴(yán)格按照你的代碼,其實(shí) n 為全局變量,我理解你的本意為 var n = 999;)。

而第一種 f1 實(shí)際上返回的是個(gè)匿名函數(shù),這樣 n 作用域被另外個(gè) f2 函數(shù)作用域所使用,因此它會(huì)保留。n 不會(huì)被重復(fù)聲明,且內(nèi)容會(huì)被保存

這是我見過(guò)最簡(jiǎn)單易懂的閉包教程。

支持下。

博主的博客寫的不錯(cuò),簡(jiǎn)單易懂,東西涉及的很多方面我都有興趣,看來(lái)是同道中人,^_^

一文中的!!!!!!!!!!!!
學(xué)習(xí)了!!

想知道思考題的答案,
我以為是:My Object

頂樓主,我讀了一些文章。不是特明白。
有個(gè)問(wèn)題。
記得有人說(shuō)。外面的函數(shù)是closure,
好像樓主說(shuō)里面的函數(shù)是closure.

不知道到底哪個(gè)是?謝謝。

樓主講講最后一個(gè)思考題,沒明白

請(qǐng)版主講一講最后一個(gè)例子怎么回事,沒有看明白

函數(shù)中的this一般是指向window中的變量。

                引用hou的發(fā)言:
              
請(qǐng)版主講一講最后一個(gè)例子怎么回事,沒有看明白

上面本人說(shuō)得不太正確。
this的指向是由它所在函數(shù)調(diào)用的上下文決定的,而不是由它所在函數(shù)定義的上下文決定的。

如果非要指向object,可顯式的控制--把代碼的最后一句改為 alert(object.getName().call(object));

阮大哥講的很透徹 受益匪淺

大道至簡(jiǎn),給予我這個(gè)初學(xué)者很大的幫助,謝謝!

淺顯易懂,很好。

如下看法,認(rèn)為有待商榷:
#1、有一個(gè)地方需要注意,函數(shù)內(nèi)部聲明變量的時(shí)候,一定要使用var命令。如果不用的話,你實(shí)際上聲明了一個(gè)全局變量!

#2、這段代碼中另一個(gè)值得注意的地方,就是“nAdd=function(){n+=1}”這一行,首先在nAdd前面沒有使用var關(guān)鍵字,因此nAdd是一個(gè)全局變量,而不是局部變量。其次,nAdd的值是一個(gè)匿名函數(shù)(anonymous function),而這個(gè)匿名函數(shù)本身也是一個(gè)閉包,所以nAdd相當(dāng)于是一個(gè)setter,可以在函數(shù)外部對(duì)函數(shù)內(nèi)部的局部變量進(jìn)行操作。

  function f1(){
test = 10;
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
//如果 #1 說(shuō)法正確,下句會(huì)打印10,實(shí)際結(jié)果是test未定義。
//alert(test); // error test 未定義

//如果 #2 正確,語(yǔ)句 nAdd(); 位置在何處應(yīng)該都能執(zhí)行,測(cè)試結(jié)果在下面這個(gè)位置,也就是語(yǔ)句 var result=f1(); 前。是不能執(zhí)行的。
//nAdd();
var result=f1();
result(); // 999
  nAdd();
result(); // 1000

To 過(guò)客:

函數(shù)內(nèi)部定義的方法和變量,要等到函數(shù)執(zhí)行過(guò)以后,才會(huì)真正定義

但是從過(guò)客說(shuō)的里面可以引出另外的問(wèn)題,當(dāng)使用這樣的代碼時(shí)。

  function f1(){
test = 10;
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }

如果在函數(shù)f1定義之前添加變量定義

              var n = 1;
            
然后調(diào)用
              f1()();
            
則顯示為999。說(shuō)明nAdd中的n確實(shí)是作為全局變量存在。于是問(wèn)題就來(lái)了——有什么方法讓他可以是父函數(shù)中定義的n呢?

?

大道至簡(jiǎn),很不錯(cuò)!~ 這篇文章我要轉(zhuǎn)了...

                引用George Wing的發(fā)言:
              

函數(shù)中的this一般是指向window中的變量。

this關(guān)鍵字代表的實(shí)例會(huì)根據(jù)環(huán)境不同而變化的. 他總是指向owner 看看這篇你大概就動(dòng)this這個(gè)關(guān)鍵字了

http://www.quirksmode.org/js/this.html

最后一個(gè)題感覺和閉包沒什么關(guān)系啊,能詳細(xì)解釋一下嗎?因?yàn)楫?dāng)一個(gè)函數(shù)作為函數(shù)而不是方法來(lái)調(diào)用的時(shí)候,this指向的是全局對(duì)象,這在《Javascript權(quán)威指南》上說(shuō)的很清楚,所以答案肯定是“The Window”,和閉包沒什么關(guān)系啊

最后一題重點(diǎn)在this

如果把f2申明成全局變量,道理一樣嗎?

太經(jīng)典了!
終于理解了,一箭雙雕啊!既理解了this的用法,又理解了閉包

這個(gè)例子很不錯(cuò),真的是一箭雙雕

前面講得挺好的,淺顯易懂。對(duì)最后的兩個(gè)例子搞不清楚為啥。版主能不能具體分析下。
var obj=function()
{
var MyFunc=function()
{
alert("hello world");
}
return function()
{
return MyFunc;
}
}()
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂

最后兩個(gè)例子很精煉 ^ ^

嘗試解答代碼段一:
getNameFunc: function() {//假設(shè)函數(shù)名為A
return function()/*假設(shè)函數(shù)名為B*/ { return this.name; };
}
在函數(shù)里面構(gòu)建函數(shù)的時(shí)候,閉包產(chǎn)生。
在函數(shù)B內(nèi)調(diào)用函數(shù)A的this.name,由于函數(shù)A沒有name屬性,所以就去找全局變量name,找到了,所以返回“The Window”,要是沒有找到,則返回“undefined”。

代碼段二可以嘗試將代碼更改為:
var _this = this;
return function() { return _this.name +"__"+ this.name; };

只有一點(diǎn)沒弄懂,如下代碼,nAdd在函數(shù)外為什么可以有意義?而test不行?想了好久,不知道那里有解答
  function f1(){
test=10;
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }

通俗易懂,, 閱覽無(wú)數(shù)教程, 看了這篇, 終于明白了點(diǎn).

寫得太好了

這篇文章是阮兄一貫的風(fēng)格,我喜歡,不過(guò) "Javascript語(yǔ)言的特殊之處,就在于函數(shù)內(nèi)部可以直接讀取全局變量。"這句有點(diǎn)奇怪,c不一樣可以在函數(shù)內(nèi)部直接讀取全局變量么?難道不是么?

阮大哥能不能具體講下最后的思考題啊? 感覺關(guān)鍵在this

變量的作用域無(wú)非就是兩種:全局變量和局部變量。
這句話值得商榷, 變量的作用域確實(shí)只有兩種, 不過(guò)他們是全局對(duì)象和函數(shù).
你想說(shuō)的或許是變量的類型有兩種?

理解最后兩個(gè)例子:

1 函數(shù)中的this指的是調(diào)用這個(gè)函數(shù)的owner
2 object.getNameFunc()是返回一個(gè)函數(shù),并沒有執(zhí)行函數(shù)中的代碼
3 增加一個(gè)例子0:

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
return (this.name);
      }
  };
var name = object.getNameFunc();
  alert(name);

4 把例子1變成

  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name; //這個(gè)this是有上下文的限制的
      };
    }
  };
var tmp = Object.getNameFunc(); //此時(shí)沒有執(zhí)行this.name
var name = tmp();//這個(gè)時(shí)候才執(zhí)行,這時(shí)候的this上下文為全局
alert(name);
//alert(object.getNameFunc()())

5 把例子2變成:

var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
var tmp = Object.getNameFunc(); //這個(gè)時(shí)候執(zhí)行了that = this,這里的this上下文是object,所以that指的是object
var name = Object.getNameFunc(); //這個(gè)時(shí)候執(zhí)行了that.name
alert(name);
//alert(object.getNameFunc()());

                引用Jason的發(fā)言:
              

但是從過(guò)客說(shuō)的里面可以引出另外的問(wèn)題,當(dāng)使用這樣的代碼時(shí)。

  function f1(){
test = 10;
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }

如果在函數(shù)f1定義之前添加變量定義var n = 1;然后調(diào)用f1()();則顯示為999。說(shuō)明nAdd中的n確實(shí)是作為全局變量存在。于是問(wèn)題就來(lái)了——有什么方法讓他可以是父函數(shù)中定義的n呢?

              var n = 1;
function f1(){
	var n = 999;
	nAdd = function(){
		n++;
	}
	function f2(){
		alert(n);
	}
	return f2;
}
var b = f1();
nAdd();//n = 999+1 = 1000
b();//彈出 n 的值是 1000 (閉包內(nèi)的變量n)
alert(n);//彈出n的值是 1 (全局)

            
全局的函數(shù) nAdd 和 由f1返回的函數(shù)中 所使用到的變量n全部為f1函數(shù)內(nèi)的局部變量n,而不是全局變量n,證據(jù)就是上面的代碼中最后一句 alert(n) 彈出的值是1, 也就是說(shuō) nAdd中的n++并沒有改變?nèi)肿兞恐衝的值.

你自己描述的是 f1()() 顯示的是999,說(shuō)明 n 是使用的f1內(nèi)部的變量n,而非是全局變量n,不知道你為什么會(huì)有

說(shuō)明nAdd中的n確實(shí)是作為全局變量存在。
這種想法呢? 如果想在nAdd中使用全局變量n(即在函數(shù)外面定義的n)的話,使用window.n來(lái)訪問(wèn).

?

樓主文章中的:


二、如何從外部讀取局部變量?

這一整大段中的
n=999;

根據(jù)整篇文章所表達(dá)的內(nèi)容,應(yīng)該為:
var n=999;

因?yàn)槿绻麤]有加var,則聲明的是全局變量,既然是全局變量,則在所有函數(shù)內(nèi)部都是可見的,也就不會(huì)存在閉包這種說(shuō)法.

?

請(qǐng)求樓主修正.

                引用小彘的發(fā)言:
              

前面講得挺好的,淺顯易懂。對(duì)最后的兩個(gè)例子搞不清楚為啥。版主能不能具體分析下。
var obj=function()
{
var MyFunc=function()
{
alert("hello world");
}
return function()
{
return MyFunc;
}
}()
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂

因?yàn)閒3和f4都指向同一個(gè)地址(即MyFunc).


var obj = (function() {
var MyFunc=function() {
alert("hello world");
}
return function() {
return MyFunc;
}
})();
var f3=obj();
var f4=obj();
alert(f3 === f4);//為啥是TRUE;搞不懂

?

我測(cè)試了一下,為什么第一個(gè)例子輸出的什么都沒有是null,第二個(gè)我理解是myobject。誰(shuí)能解釋下

                引用小秦的發(fā)言:
              

請(qǐng)求樓主修正.

謝謝指出,已更正。

起初以為函數(shù)內(nèi)用var聲明變量,就等于用了this聲明,其實(shí)不是
var w=100;
function f1(){
//var w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:100

var w=100;
function f1(){
var w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:100

var w=100;
function f1(){
w=101;
//this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:101

var w=100;
function f1(){
//var w=101;
this.w=102;
function f2(){
document.write(this.w);
}
return f2;
}
f1()();
輸出:102

看起來(lái)函數(shù)中的var和this并不是一個(gè)概念,函數(shù)內(nèi)的局部變量與函數(shù)的屬性不是一回事,不過(guò)通過(guò)上面的情況能夠加深理解this和閉包

很不錯(cuò)的講解,樓主寫的通俗易懂,很棒的理解,很受用!我的qq:290913917 希望有機(jī)會(huì)成為共同研究javascript和html5的伙伴,謝謝!

我感覺第一個(gè)思考題是不是這樣理解:
首先this指向的是當(dāng)前運(yùn)行該函數(shù)的對(duì)象,
1、object.getNameFunc()得到了一個(gè)函數(shù),函數(shù)為function(){return this.name}
2、object.getNameFunc()(),此時(shí)為window運(yùn)行該函數(shù),所以this指向的是window,所以this.name為The window

做習(xí)題之前有一點(diǎn)需要很清楚:

內(nèi)部函數(shù)可以訪問(wèn)定義它們的外部函數(shù)的參數(shù)和變量(除了this和arguments之外)
如果需要訪問(wèn)對(duì)象的name屬性的話,就需要顯示的定義一個(gè)變量that來(lái)引用this,而這個(gè)變量此時(shí)就指向object對(duì)象了。

第一題改成下面這樣就很清楚了。getNameFunc的第一個(gè)()是屬于方法調(diào)用,所以this綁定到了object對(duì)象,自然this.name為"My Object",但是閉包函數(shù)無(wú)法訪問(wèn)這個(gè)this,它只能訪問(wèn)到全局的this。

var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
alert(this.name);
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());

寫的真不錯(cuò)。。。看了很多文章講閉包都是云里霧里的。。看了本文才恍然大悟。。。哦原來(lái)閉包如此簡(jiǎn)單。。。。樓主寫的不錯(cuò)。。。

前面講的我都明白,但是最后兩個(gè)例子還是不明白,好多處都不懂!
1. var object = {。。。} 這是在干什么?是在聲明一個(gè)變量?還是在聲明一個(gè)類,然后里面有許多屬性?

2 . object.getNameFunc()(); 怎么會(huì)有兩個(gè)括號(hào)?


3. 如何判斷 this指向的是object 對(duì)象還是全局對(duì)象 ?

閉包是運(yùn)行時(shí)中的概念,不能講哪個(gè)函數(shù)是一個(gè)閉包!而是哪個(gè)函數(shù)在運(yùn)行時(shí)存在一個(gè)閉包!有時(shí)候,好幾個(gè)函數(shù)都可以組成一個(gè)閉包呢:
function ff()
{
var local=1;
this.add1=function()
{
return ++local;
};
this.add2=function()
{
return ++local;
}
}

var f=new ff();

alert(f.add1());//2
alert(f.add2());//3

最后兩個(gè)例子中,第一個(gè)其實(shí)不是閉包,第二個(gè)是,但第二個(gè)例子其實(shí)不用那么復(fù)雜,直接把第一個(gè)例子中的this去掉就可以了。

為什么第一個(gè)運(yùn)行以后結(jié)果是result?!既不是window也不是object....???

學(xué)習(xí)Javascript閉包(Closure)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 91在线 | 欧美:| 色站综合 | 午夜久久久久久 | 久久精品国产99国产精品 | 欧亚在线视频 | 欧美白人猛性xxxxx交69 | 爱爱视频欧美 | 无夜精品久久久久久 | 亚洲欧美日韩国产精品影院 | 亚洲精品国产福利一区二区三区 | 国产精品99精品久久免费 | 久久国产网站 | 毛片一级视频 | www.四虎在线| 欧美成人精品一区二三区在线观看 | 成人免费视频网 | aaaa级片| 久久综合伊人 | 久操这里只有精品 | 在线观看视频国产 | 九九99久麻豆精品视传媒 | 天天干天天草天天 | 草草影院一级毛片a级 | 欧美激情一区二区三区视频 | 久久精品免费观看久久 | 一级毛片一级毛片一级毛片aa | 日韩欧美一二区 | 国产精品视频不卡 | 手机在线看片福利 | 99热成人精品国产免国语的 | 欧美观看一级毛片 | 日韩欧美视频一区 | 国产精品久久久久国产精品 | 九九精品久久久久久久久 | 亚洲涩涩精品专区 | 香蕉视频一级片 | 国内精品自在自线香蕉 | 奇米影视444| 曰本一区二区三区 | 男女啪啪猛烈免费网站 | 国产一级特黄aa级特黄裸毛片 |