超碰91资源站-超碰97豆花-超碰97人妻-超碰97人人干-超碰97人人香蕉-超碰97天天操-超碰97在线资源站-超碰97资源站共享-超碰97资源站总站-超碰aa在线91-超碰av操-超碰爱爱

半岛外围网上直营

JavaScript對象模型-執行模型

原創|其它|編輯:郝浩|2009-12-28 10:19:24.000|閱讀 519 次

概述:簡單數值類型: 有Undefined, Null, Boolean, Number和String。注意,描述中的英文單詞在這里僅指數據類型的名稱,并不特指JS的全局對象N an, Boolean, Number, String等,它們在概念上的區別是比較大的。 對象: 一個無序屬性的集合,這些屬性的值為簡單數值類型、對象或者函數。同上,這里的對象并不特指全局對象Object。

# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>

數據類型
基本數據類型
基本數據類型是JS語言最底層的實現。
簡單數值類型: 有Undefined, Null, Boolean, Number和String。注意,描述中的英文單詞在這里僅指數據類型的名稱,并不特指JS的全局對象N an, Boolean, Number, String等,它們在概念上的區別是比較大的。
對象: 一個無序屬性的集合,這些屬性的值為簡單數值類型、對象或者函數。同上,這里的對象并不特指全局對象Object。
函數: 函數是對象的一種,實現上內部屬性[[Class]]值為"Function",表明它是函數類型,除了對象的內部屬性方法外,還有[[Construct]]、[[Call]]、[[Scope]]等內部屬性。函數作為函數調用與構造器(使用new關鍵字創建實例對象)的處理機制不一樣(Function對象除外),內部方法[[Construct]]用于實現作為構造器的邏輯,方法[[Call]]實現作為函數調用的邏輯。同上,這里的函數并不特指全局對象Function。
函數在JS這個Prototype語言中可以看作是面向對象語言的類,可以用它來構造對象實例。既然函數可以看作是類,所以每一個函數可以看作是一種擴展數據類型。

內置數據類型(內置對象)
Function: 函數類型的用戶接口。
Object: 對象類型的用戶接口。
Boolean, Number, String: 分別為這三種簡單數值類型的對象包裝器,對象包裝在概念上有點類似C#中的Box/Unbox。
Date, Array, RegExp: 可以把它們看作是幾種內置的擴展數據類型。

首先,Function, Object, Boolean, Number, String, Date, Array, RegExp等都是JavaScript語言的內置對象,它們都可以看作是函數的派生類型,例如Number instanceof Function為true,Number instanceof Object為true。在這個意義上,可以將它們跟用戶定義的函數等同看待。
其次,它們各自可以代表一種數據類型,由JS引擎用native code或內置的JS代碼實現,是暴露給開發者對這些內置數據類型進行操作的接口。在這個意義上,它們都是一種抽象的概念,后面隱藏了具體的實現機制。
在每一個提到Number, Function等單詞的地方,應該迅速的在思維中將它們實例化為上面的兩種情況之一。

數據類型實現模型描述
   
Build-in *** data structure: 指JS內部用于實現***類型的數據結構,這些結構我們基本上無法直接操作。
Build-in *** object: 指JS內置的Number, String, Boolean等這些對象,這是JS將內部實現的數據類型暴露給開發者使用的接口。
 Build-in *** constructor: 指JS內置的一些構造器,用來構造相應類型的對象實例。它們被包裝成函數對象暴露出來,例如我們可以使用下面的方法訪問到這些函數對象:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
//
access the build-in number constructor
var number = new Number(123);
var numConstructor1 = number.constructor; //or
var numConstructor2 = new Object(123).constructor;
//both numConstructor1 and numConstructor2 are the build-in Number constructor
numConstructor1 == numConstructor2 //result: true
//
access the build-in object constructor
var objConstructor1 = {}.constructor; //or
var objConstructor2 = new Object().constructor;
//both objConstructor1 and objConstructor2 are the build-in Object constructor
objConstructor1==objConstructor2 //result: true


具體實現上,上圖中橫向之間可能也存在關聯,例如對于build-in data structure和constructor,Function、 Date、 Array、 RegExp等都可以繼承Object的結構而實現,但這是具體實現相關的事情了。

關于簡單數值類型的對象化
這是一個細微的地方,下面描述對于Boolean, String和Number這三種簡單數值類型都適用,以Number為例說明。
JS規范要求: 使用var num1=123;這樣的代碼,直接返回基本數據類型,就是說返回的對象不是派生自Number和Object類型,用num1 instanceof Object測試為false;使用new關鍵字創建則返回Number類型,例如var num2=new Number(123); num2 instanceof Number為true。
將Number當作函數調用,返回結果會轉換成簡單數值類型。下面是測試代碼:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var num1 = new Number(123); //num1 derived from Number & Object
num1 instanceof Number //result: true
num1 instanceof Object //result: true
//convert the num1 from Number type to primitive type, so it's no longer an instance of Number or Object
num1 = Number(num1);
num1 instanceof Number //result: false
num1 instanceof Object //result: false
var num2 = 123//num2 is a primitive type
num2 instanceof Number //result: false
num2 instanceof Object //result: false

雖然我們得到了一個簡單數值類型,但它看起來仍然是一個JS Object對象,具有Object以及相應類型的所有屬性和方法,使用上基本沒有差別,唯一不同之處是instanceof的測試結果。

Prototype繼承
Prototype

每個對象都有一個[[Prototype]]的內部屬性,它的值為null或者另外一個對象。函數對象都有一個顯示的prototype屬性,它并不是內部[[Prototype]]屬性。不同的JS引擎實現者可以將內部[[Prototype]]屬性命名為任何名字,并且設置它的可見性,只在JS引擎內部使用。雖然無法在JS代碼中訪問到內部[[Prototype]](FireFox中可以,名字為__proto__因為Mozilla將它公開了),但可以使用對象的isPrototypeOf()方法進行測試,注意這個方法會在整個Prototype鏈上進行判斷。
使用obj.propName訪問一個對象的屬性時,按照下面的步驟進行處理(假設obj的內部[[Prototype]]屬性名為__proto__):
1. 如果obj存在propName屬性,返回屬性的值,否則
2. 如果obj.__proto__為null,返回undefined,否則
3. 返回obj.__proto__.propName
調用對象的方法跟訪問屬性搜索過程一樣,因為方法的函數對象就是對象的一個屬性值。
提示: 上面步驟中隱含了一個遞歸過程,步驟3中obj.__proto__是另外一個對象,同樣將采用1, 2, 3這樣的步驟來搜索propName屬性。

例如下圖所示,object1將具備屬性prop1, prop2, prop3以及方法fn1, fn2, fn3。圖中虛線箭頭表示prototype鏈。
   
這就是基于Prototype的繼承和共享。其中object1的方法fn2來自object2,概念上即object2重寫了object3的方法fn2。
JavaScript對象應當都通過prototype鏈關聯起來,最頂層是Object,即對象都派生自Object類型。

類似C++等面向對象語言用類(被抽象了的類型)來承載方法,用對象(實例化對象)承載屬性,Prototype語言只用實例化的對象來承載方法和屬性。本質區別是前者基于內存結構的描述來實現繼承,后者基于具體的內存塊實現。

對象創建過程
JS中只有函數對象具備類的概念,因此要創建一個對象,必須使用函數對象。函數對象內部有[[Construct]]方法和[[Call]]方法,[[Construct]]用于構造對象,[[Call]]用于函數調用,只有使用new操作符時才觸發[[Construct]]邏輯。
var obj=new Object(); 是使用內置的Object這個函數對象創建實例化對象obj。var obj={};和var obj=[];這種代碼將由JS引擎觸發Object和Array的構造過程。function fn(){}; var myObj=new fn();是使用用戶定義的類型創建實例化對象。

new Fn(args)的創建過程如下(即函數對象的[[Construct]]方法處理邏輯,對象的創建過程)。另外函數對象本身的創建過程(指定義函數或者用Function創建一個函數對象等方式)雖然也使用了下面的處理邏輯,但有特殊的地方,后面再描述。
1. 創建一個build-in object對象obj并初始化
2. 如果Fn.prototype是Object類型,則將obj的內部[[Prototype]]設置為Fn.prototype,否則obj的[[Prototype]]將為其初始化值(即Object.prototype)
3. 將obj作為this,使用args參數調用Fn的內部[[Call]]方法
    3.1 內部[[Call]]方法創建當前執行上下文
    3.2 調用F的函數體
    3.3 銷毀當前的執行上下文
    3.4 返回F函數體的返回值,如果F的函數體沒有返回值則返回undefined
4. 如果[[Call]]的返回值是Object類型,則返回這個值,否則返回obj
注意步驟2中, prototype指對象顯示的prototype屬性,而[[Prototype]]則代表對象內部Prototype屬性(隱式的)。
構成對象Prototype鏈的是內部隱式的[[Prototype]],而并非對象顯示的prototype屬性。顯示的prototype只有在函數對象上才有意義,從上面的創建過程可以看到,函數的prototype被賦給派生對象隱式[[Prototype]]屬性,這樣根據Prototype規則,派生對象和函數的prototype對象之間才存在屬性、方法的繼承/共享關系。

用代碼來做一些驗證:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(){}
//the value of implicit [[Prototype]] property of those objects derived from fn will be assigned to fn.prototype
fn.prototype={ attr1:"aaa", attr2:"bbb"};
var obj=new fn();
document.write(obj.attr1 
+ "<br />"); //result: aaa
document.write(obj.attr2 + "<br />"); //result: bbb
document.write(obj instanceof fn); //result: true
document.write("<br />");
//I change the prototype of fn here, so by the algorithm of Prototype the obj is no longer the instance of fn,
//
but this won't affect the obj and its [[Prototype]] property, and the obj still has attr1 and attr2 properties
fn.prototype={};
document.write(obj.attr1 
+ "<br />"); //result: aaa
document.write(obj.attr2 + "<br />"); //result: bbb
document.write(obj instanceof fn); //result: false

關于創建過程返回值的驗證:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(){
   
//according to step 4 described above,
    //the new fn() operation will return the object { attr1: 111, attr2: 222 }, it's not an instance of fn!
    return { attr1: 111, attr2: 222 };
}
fn.prototype
={ attr1:"aaa", attr2:"bbb"};
var obj=new fn();
document.write(obj.attr1 
+ "<br />"); //result: 111
document.write(obj.attr2 + "<br />"); //result: 222
document.write(obj instanceof fn); //result: false


做個練習
經過上面的理解應,請寫出下面這幅圖的實現代碼。圖中CF是一個函數,Cfp是CF的prototype對象,cf1, cf2, cf3, cf4, cf5都是CF的實例對象。虛線箭頭表示隱式Prototype關系,實線箭頭表示顯示prototype關系。
   
供參考的實現方案:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function CF(q1, q2){
    
this.q1=q1;
    
this.q2=q2;
}
CF.P1
="P1 in CF"; 
CF.P2
="P2 in CF";
function Cfp(){
    
this.CFP1="CFP1 in Cfp";
}
CF.prototype
=new Cfp();
var cf1=new CF("aaa""bbb");
document.write(cf1.CFP1 
+ "<br />"); //result: CFP1 in Cfp
document.write(cf1.q1 + "<br />"); //result: aaa
document.write(cf1.q2 + "<br />"); //result: bbb


本地屬性與繼承屬性
對象通過隱式Prototype鏈能夠實現屬性和方法的繼承,但prototype也是一個普通對象,就是說它是一個普通的實例化的對象,而不是純粹抽象的數據結構描述。所以就有了這個本地屬性與繼承屬性的問題。
首先看一下設置對象屬性時的處理過程。JS定義了一組attribute,用來描述對象的屬性property,以表明屬性property是否可以在JavaScript代碼中設值、被for in枚舉等。
obj.propName=value的賦值語句處理步驟如下:
1. 如果propName的attribute設置為不能設值,則返回
2. 如果obj.propName不存在,則為obj創建一個屬性,名稱為propName
3. 將obj.propName的值設為value
可以看到,設值過程并不會考慮Prototype鏈,道理很明顯,obj的內部[[Prototype]]是一個實例化的對象,它不僅僅向obj共享屬性,還可能向其它對象共享屬性,修改它可能影響其它對象。
 用上面CF, Cfp的示例來說明,實例對象cf1具有本地屬性q1, q2以及繼承屬性CFP1,如果執行cf1.CFP1="",那么cf1就具有本地屬性CFP1了,測試結果如下:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var cf1=new CF("aaa""bbb");
var cf2=new CF(111222);
document.write(cf1.CFP1 
+ "<br />"); //result: CFP1 in Cfp
document.write(cf2.CFP1 + "<br />"); //result: CFP1 in Cfp
//it will result in a local property in cf1
cf1.CFP1="new value for cf1";
//changes on CF.prototype.CFP1 will affect cf2 but not cf1, because there's already a local property with
//the name CFP1 in cf1, but no such one in cf2
CF.prototype.CFP1="new value for Cfp";
document.write(cf1.CFP1 
+ "<br />"); //result: new value for cf1
document.write(cf2.CFP1 + "<br />"); //result: new value for Cfp


語義上的混亂?
還是使用上面CF, Cfp示例的場景。
根據Prototype的機制,我們可以說對象cf1, cf2等都繼承了對象Cfp的屬性和方法,所以應該說他們之間存在繼承關系。屬性的繼承/共享是沿著隱式Prototype鏈作用的,所以繼承關系也應當理解為沿著這個鏈。
我們再看instanceOf操作,只有cf1 instanceOf CF才成立,我們說cf1是CF的實例對象,CF充當了類的角色,而不會說cf1是Cfp的實例對象,這樣我們應當說cf1繼承自CF? 但CF充當的只是一個第三方工廠的角色,它跟cf1之間并沒有屬性繼承這個關系。
把CF, Cfp看作一個整體來理解也同樣牽強。

Prototype就是Prototype,沒有必要強把JavaScript與面向對象概念結合起來, JavaScript只具備有限的面向對象能力,從另外的角度我們可以把它看成函數語言、動態語言,所以它是吸收了多種語言特性的精簡版。

對象模型
Where are we?
1. 了解了JavaScript的數據類型,清楚了象Number這樣的系統內置對象具有多重身份: a)它們本身是一個函數對象,只是由引擎內部實現而已,b)它們代表一種數據類型,我們可以用它們定義、操作相應類型的數據,c)在它們背后隱藏了引擎的內部實現機制,例如內部的數據結構、各種被包裝成了JavaScript對象的構造器等。
2. 了解了Prototype機制,知道對象是如何通過它們繼承屬性和方法,知道了在創建對象過程中JS引擎內部是如何設置Prototype關系的。

接下來對用戶自定義函數對象本身的創建過程進行了解之后,我們就可以對JavaScript的對象模型來一個整體性的overview了。

函數對象創建過程
JavaScript代碼中定義函數,或者調用Function創建函數時,最終都會以類似這樣的形式調用Function函數:var newFun=Function(funArgs, funBody); 。創建函數對象的主要步驟如下:
1. 創建一個build-in object對象fn
2. 將fn的內部[[Prototype]]設為Function.prototype
3. 設置內部的[[Call]]屬性,它是內部實現的一個方法,處理邏輯參考對象創建過程的步驟3
4. 設置內部的[[Construct]]屬性,它是內部實現的一個方法,處理邏輯參考對象創建過程的步驟1,2,3,4
5. 設置fn.length為funArgs.length,如果函數沒有參數,則將fn.length設置為0
6. 使用new Object()同樣的邏輯創建一個Object對象fnProto
7. 將fnProto.constructor設為fn
8. 將fn.prototype設為fnProto
9. 返回fn
步驟1跟步驟6的區別為,步驟1只是創建內部用來實現Object對象的數據結構(build-in object structure),并完成內部必要的初始化工作,但它的[[Prototype]]、[[Call]]、[[Construct]]等屬性應當為null或者內部初始化值,即我們可以理解為不指向任何對象(對[[Prototype]]這樣的屬性而言),或者不包含任何處理(對[[Call]]、[[Construct]]這樣的方法而言)。步驟6則將按照前面描述的對象創建過程創建一個新的對象,它的[[Prototype]]等被設置了。
從上面的處理步驟可以了解,任何時候我們定義一個函數,它的prototype是一個Object實例,這樣默認情況下我們創建自定義函數的實例對象時,它們的Prototype鏈將指向Object.prototype。
另外,Function一個特殊的地方,是它的[[Call]]和[[Construct]]處理邏輯一樣。

JavaScript對象模型
   
紅色虛線表示隱式Prototype鏈。
 這張對象模型圖中包含了太多東西,不少地方需要仔細體會,可以寫些測試代碼進行驗證。徹底理解了這張圖,對JavaScript語言的了解也就差不多了。下面是一些補充說明:
 1. 圖中有好幾個地方提到build-in Function constructor,這是同一個對象,可以測試驗證:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
Function==Function.constructor //result: true
Function==Function.prototype.constructor //result: true
Function==Object.constructor //result: true
//
Function also equals to Number.constructor, String.constructor, Array.constructor, RegExp.constructor, etc.
function fn(){}
Function
==fn.constructor //result: true

這說明了幾個問題: Function指向系統內置的函數構造器(build-in Function constructor);Function具有自舉性;系統中所有函數都是由Function構造。

2. 左下角的obj1, obj2...objn范指用類似這樣的代碼創建的對象: function fn1(){}; var obj1=new fn1();
    這些對象沒有本地constructor方法,但它們將從Prototype鏈上得到一個繼承的constructor方法,即fn.prototype.constructor,從函數對象的構造過程可以知道,它就是fn本身了。
    右下角的obj1, obj2...objn范指用類似這樣的代碼創建的對象: var obj1=new Object();或var obj1={};或var obj1=new Number(123);或obj1=/\w+/;等等。所以這些對象Prototype鏈的指向、從Prototype鏈繼承而來的constructor的值(指它們的constructor是build-in Number constructor還是build-in Object constructor等)等依賴于具體的對象類型。另外注意的是,var obj=new Object(123);這樣創建的對象,它的類型仍然是Number,即同樣需要根據參數值的類型來確定。
    同樣它們也沒有本地constructor,而是從Prototype鏈上獲得繼承的constructor方法,即build-in *** constructor,具體是哪一個由數據類型確定。

3. 關于圖中Prototype鏈的補充說明:
Object.prototype是整個鏈的終結點,它的內部[[Prototype]]為null。
所有函數的Prototype鏈都指向Function.prototype。
Function的Prototype鏈指向Function.prototype,這是規范要求的,因為設計者將Function設計為具有自舉性。Function的Prototype鏈這樣設計之后,Function.constructor==Function, Function instanceOf Function都為true。另外Function已經是最頂層的構造器,但Function本身也是一個函數對象,它必然是由某個東西創建出來的,這樣自舉在語義上合情合理。
Function.prototype的Prototype鏈指向Object.prototype,這也是規范強制要求的。首先Function.prototype是Function的一個實例對象(typeof Function.prototype可以知道它是一個Function,instanceOf無法通過測試,因為Prototype鏈在內部被額外設置了),所以按照Prototype的規則,Function.prototype的內部[[Prototype]]值應當為Function.prototype這個對象,即它的Prototype鏈指向自己本身。這樣一方面在Prototype鏈上造成一個死循環,另一方面它本身成為了一個終結點,結果就是所有函數對象將不是派生自Object了。加上這個強制要求之后,Prototype鏈只有唯一的一個終結點。

4. 因為Function.prototype是一個函數對象,所以它應當具有顯示的prototype屬性,即Function.prototype.prototype,但只有FireFox中可以訪問到,IE、Opera、Safari都無法訪問。所以圖中用了個表示不存在的符號。

5. 用戶自定義函數(user defined functions)默認情況下[[Prototype]]值是Object.prototype,即它的隱式Prototype鏈指向Object.prototype,所以圖中就這樣表示了,但并不代表總是這樣,當用戶設置了自定義函數的prototype屬性之后,情況就不同了。

執行模型
執行上下文(Execution Context)簡介
JavaScript代碼運行的地方都存在執行上下文,它是一個概念,一種機制,用來完成JavaScript運行時作用域、生存期等方面的處理。執行上下文包括Variable Object、Variable Instatiation、Scope/Scope Chain等概念,在不同的場景/執行環境下,處理上存在一些差異,下面先對這些場景進行說明。

函數對象分為用戶自定義函數對象和系統內置函數對象,對于用戶自定義函數對象將按照下面描述的機制進行處理,但內置函數對象與具體實現相關,ECMA規范對它們執行上下文的處理沒有要求,即它們基本不適合本節描述的內容。

執行的JavaScript代碼分三種類型,后面會對這三種類型處理上不同的地方進行說明:
1. Global Code,即全局的、不在任何函數里面的代碼,例如一個js文件、嵌入在HTML頁面中的js代碼等。
2. Eval Code,即使用函數動態執行的JS代碼。
3. Function Code,即用戶自定義函數中的函數體JS代碼。

基本原理
在用戶自定義函數中,可以傳入參數、在函數中定義局部變量,函數體代碼可以使用這些入參、局部變量。背后的機制是什么樣呢?
當JS執行流進入函數時,JavaScript引擎在內部創建一個對象,叫做Variable Object。對應函數的每一個參數,在Variable Object上添加一個屬性,屬性的名字、值與參數的名字、值相同。函數中每聲明一個變量,也會在Variable Object上添加一個屬性,名字就是變量名,因此為變量賦值就是給Variable Object對應的屬性賦值。在函數中訪問參數或者局部變量時,就是在variable Object上搜索相應的屬性,返回其值。
一般情況下Variable Object是一個內部對象,JS代碼中無法直接訪問。規范中對其實現方式也不做要求,因此它可能只是引擎內部的一種數據結構。

大致處理方式就這樣,但作用域的概念不只這么簡單,例如函數體中可以使用全局變量、函數嵌套定義時情況更復雜點。這些情況下怎樣處理?JavaScript引擎將不同執行位置上的Variable Object按照規則構建一個鏈表,在訪問一個變量時,先在鏈表的第一個Variable Object上查找,如果沒有找到則繼續在第二個Variable Object上查找,直到搜索結束。這就是Scope/Scope Chain的大致概念。

下面是各個方面詳細的處理。

Global Object
JavaScript的運行環境都必須存在一個唯一的全局對象-Global Object,例如HTML中的window對象。Global Object是一個宿主對象,除了作為JavaScript運行時的全局容器應具備的職責外,ECMA規范對它沒有額外要求。它包Math、String、Date、parseInt等JavaScript中內置的全局對象、函數(都作為Global Object的屬性),還可以包含其它宿主環境需要的一些屬性。

Variable Object
上面簡述了Variable Object的基本概念。創建Variable Object,將參數、局部變量設置為Variable Object屬性的處理過程叫做Variable Instatiation-變量實例化,后面結合Scope Chain再進行詳細說明。

Global Code
 Variable Object就是Global Object,這是Variable Object唯一特殊的地方(指它是內部的無法訪問的對象而言)。

var globalVariable = "WWW";
document.write(window.globalVariable); 
//result: WWW

上面代碼在Global Code方式下運行,根據對Variable Object的處理,定義變量globalVariable時就會在Global Object(即window)對象上添加這個屬性,所以輸出是WWW這個值。

Function Code
Variable Object也叫做Activation Object(因為有一些差異存在,所以規范中重新取一個名字以示區別,Global Code/Eval Code中叫Variable Object,Function Code中就叫做Activation Object)。
每次進入函數執行都會創建一個新的Activation Object對象,然后創建一個arguments對象并設置為Activation Object的屬性,再進行Variable Instantiation處理。
在退出函數時,Activation Object會被丟棄(并不是內存釋放,只是可以被垃圾回收了)。

附arguments對象的屬性:
length: 為實際傳入參數的個數。注意,參考函數對象創建過程,函數對象上的length為函數定義時要求的參數個數;
callee: 為執行的函數對象本身。目的是使函數對象能夠引用自己,例如需要遞歸調用的地方。
function fnName(...) { ... }這樣定義函數,它的遞歸調用可以在函數體內使用fnName完成。var fn=function(...) { ... }這樣定義匿名函數,在函數體內無法使用名字引用自己,通過arguments.callee就可以引用自己而實現遞歸調用。
參數列表: 調用者實際傳入的參數列表。這個參數列表提供一個使用索引訪問實際參數的方法。Variable Instantiation處理時會在Activation Object對象上添加屬性,前提是函數聲明時有指定參數列表。如果函數聲明中不給出參數列表,或者實際調用參數個數與聲明時的不一樣,可以通過arguments訪問各個參數。

 arguments中的參數列表與Activation Object上的參數屬性引用的是相同的參數對象(如果修改,在兩處都會反映出來)。規范并不要求arguments是一個數組對象,下面是一個測試:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
var argumentsLike = { 0"aaa"12222"WWW", length: 3, callee: function() { } };
document.write(argumentsLike[
2+ "<br />"); //result: WWW
document.write(argumentsLike[1+ "<br />"); //result: 222
//
convert the argumentsLike to an Array object, just as we can do this for the arguments property
var array = [].slice.apply(argumentsLike);
document.write(array 
instanceof Array); //result: true
document.write("<br />");
document.write(array.reverse().join(
"|")); //result: WWW|222|aaa


Eval Code
 Variable Object就是調用eval時當前執行上下文中的Variable Object。在Global Code中調用eval函數,它的Variable Object就是Global Object;在函數中調用eval,它的Variable Object就是函數的Activation Object。

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(arg){
    
var innerVar = "variable in function";
    eval(
' \
        var evalVar = "variable in eval"; \
        document.write(arg + "<br />"); \
        document.write(innerVar + "<br />"); \
    
');
    document.write(evalVar);
}
fn(
"arguments for function");

輸出結果是:
arguments for function
variable in function
variable in eval
說明: eval調用中可以訪問函數fn的參數、局部變量;在eval中定義的局部變量在函數fn中也可以訪問,因為它們的Varible Object是同一個對象。

Scope/Scope Chain
首先Scope Chain是一個類似鏈表/堆棧的結構,里面每個元素基本都是Variable Object/Activation Object。
其次存在執行上下文的地方都有當前Scope Chain,可以理解為Scope Chain就是執行上下文的具體表現形式。

Global Code
Scope Chain只包含一個對象,即Global Object。在開始JavaScript代碼的執行之前,引擎會創建好這個Scope Chain結構。

Function Code
函數對象在內部都有一個[[Scope]]屬性,用來記錄該函數所處位置的Scope Chain。
創建函數對象時,引擎會將當前執行環境的Scope Chain傳給Function的[[Construct]]方法。[[Construct]]會創建一個新的Scope Chain,內容與傳入的Scope Chain完全一樣,并賦給被創建函數的內部[[Scope]]屬性。在前面函數對象創建過程一節中,這個處理位于步驟4和5之間。
進入函數調用時,也會創建一個新的Scope Chain,包括同一個函數的遞歸調用,退出函數時這個Scope Chain被丟棄。新建的Scope Chain第一個對象是Activation Object,接下來的內容與內部[[Scope]]上存儲的Scope Chain內容完全一樣。

Eval Code
進入Eval Code執行時會創建一個新的Scope Chain,內容與當前執行上下文的Scope Chain完全一樣。

實例說明
 Scope Chain的原理就上面這些,必須結合JS代碼的執行、Variable Instantiation的細節處理,才能理解上面這些如何產生作用,下面用一個簡單的場景來綜合說明。假設下面是一段JavaScript的Global Code:

var outerVar1="variable in global code";
function fn1(arg1, arg2){
    
var innerVar1="variable in function code";
    
function fn2() { return outerVar1+" - "+innerVar1+" - "+" - "+(arg1 + arg2); }
    
return fn2();
}
var outerVar2=fn1(1020);

執行處理過程大致如下:
1. 初始化Global Object即window對象,Variable Object為window對象本身。創建Scope Chain對象,假設為scope_1,其中只包含window對象。
2. 掃描JS源代碼(讀入源代碼、可能有詞法語法分析過程),從結果中可以得到定義的變量名、函數對象。按照掃描順序:
   2.1 發現變量outerVar1,在window對象上添加outerVar1屬性,值為undefined;
   2.2 發現函數fn1的定義,使用這個定義創建函數對象,傳給創建過程的Scope Chain為scope_1。將結果添加到window的屬性中,名字為fn1,值為返回的函數對象。注意fn1的內部[[Scope]]就是scope_1。另外注意,創建過程并不會對函數體中的JS代碼做特殊處理,可以理解為只是將函數體JS代碼的掃描結果保存在函數對象的內部屬性上,在函數執行時再做進一步處理。這對理解Function Code,尤其是嵌套函數定義中的Variable Instantiation很關鍵;
   2.3 發現變量outerVar2,在window對象上添加outerVar2屬性,值為undefined;
3. 執行outerVar1賦值語句,賦值為"variable in global code"。
4. 執行函數fn1,得到返回值:
   4.1 創建Activation Object,假設為activation_1;創建一個新的Scope Chain,假設為scope_2,scope_2中第一個對象為activation_1,第二個對象為window對象(取自fn1的[[Scope]],即scope_1中的內容);
   4.2 處理參數列表。在activation_1上設置屬性arg1、arg2,值分別為10、20。創建arguments對象并進行設置,將arguments設置為activation_1的屬性;
   4.3 對fn1的函數體執行類似步驟2的處理過程:
       4.3.1 發現變量innerVar1,在activation_1對象上添加innerVar1屬性,值為undefine;
       4.3.2 發現函數fn2的定義,使用這個定義創建函數對象,傳給創建過程的Scope Chain為scope_2(函數fn1的Scope Chain為當前執行上下文的內容)。將結果添加到activation_1的屬性中,名字為fn2,值為返回的函數對象。注意fn2的內部[[Scope]]就是scope_2;
   4.4 執行innerVar1賦值語句,賦值為"variable in function code"。
   4.5 執行fn2:
       4.5.1 創建Activation Object,假設為activation_2;創建一個新的Scope Chain,假設為scope_3,scope_3中第一個對象為activation_2,接下來的對象依次為activation_1、window對象(取自fn2的[[Scope]],即scope_2);
       4.5.2 處理參數列表。因為fn2沒有參數,所以只用創建arguments對象并設置為activation_2的屬性。
       4.5.3 對fn2的函數體執行類似步驟2的處理過程,沒有發現變量定義和函數聲明。
       4.5.4 執行函數體。對任何一個變量引用,從scope_3上進行搜索,這個示例中,outerVar1將在window上找到;innerVar1、arg1、arg2將在activation_1上找到。
       4.5.5 丟棄scope_3、activation_2(指它們可以被垃圾回收了)。
       4.5.6 返回fn2的返回值。
   4.6 丟棄activation_1、scope_2。
   4.7 返回結果。
5. 將結果賦值給outerVar2。

其它情況下Scope Chain、Variable Instantiation處理類似上面的過程進行分析就行了。

根據上面的實例說明,就可以解釋下面這個測試代碼的結果:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function fn(obj){
    
return {
         
//test whether exists a local variable "outerVar" on obj
        exists: Object.prototype.hasOwnProperty.call(obj, "outerVar"),
         
//test the value of the variable "outerVar"
        value: obj.outerVar
    };
}
var result1 = fn(window);
var outerVar = "WWW";
var result2 = fn(window);

document.write(result1.exists 
+ " " + result1.value); //result: true undefined
document.write("<br />");
document.write(result2.exists 
+ " " + result2.value); //result: true WWW

result1調用的地方,outerVar聲明和賦值的語句還沒有被執行,但是測試結果window對象已經擁有一個本地屬性outerVar,其值為undefined。result2的地方outerVar已經賦值,所以window.outerVar的值已經有了。實際使用中不要出現這種先使用,后定義的情況,否則某些情況下會有問題,因為會涉及到一些規范中沒有提及,不同廠商實現方式上不一致的地方。

一些特殊處理
1. with(obj) { ... }這個語法的實現方式,是在當前的Scope Chain最前面位置插入obj這個對象,這樣就會先在obj上搜索是否有相應名字的屬性存在。其它類似的還有catch語句。
2. 前面對arguments對象的詳細說明中,提到了對函數遞歸調用的支持問題,了解到了匿名函數使用arguments.callee來實現引用自己,而命名函數可以在函數體內引用自己,根據上面Scope Chain的工作原理我們還無法解釋這個現象,因為這里有個特殊處理。
任何時候創建一個命名函數對象時,JavaScript引擎會在當前執行上下文Scope Chain的最前面插入一個對象,這個對象使用new Object()方式創建,并將這個Scope Chain傳給Function的構造函數[[Construct]],最終創建出來的函數對象內部[[Scope]]上將包含這個object對象。創建過程返回之后,JavaScript引擎在object上添加一個屬性,名字為函數名,值為返回的函數對象,然后從當前執行上下文的Scope Chain中移除它。這樣函數對象的Scope Chain中第一個對象就是對自己的引用,而移除操作則確保了對函數對象創建處Scope Chain的恢復。

this關鍵字處理
執行上下文包含的另一個概念是this關鍵字。
Global Code中this關鍵字為Global Object;函數調用時this關鍵字為調用者,例如obj1.fn1(),在fn1中this對象為obj1;Eval Code中this關鍵字為當前執行上下文的Variable Object。

在函數調用時,JavaScript提供一個讓用戶自己指定this關鍵字值的機會,即每個函數都有的call、apply方法。例如:
fn1.call(obj1, arg1, arg2, ...)或者fn1.apply(obj1, argArray),都是將obj1作為this關鍵字,調用執行fn1函數,后面的參數都作為函數fn1的參數。如果obj1為null或undefined,則Global Object將作為this關鍵字的值;如果obj1不是Object類型,則轉化為Object類型。它們之間的唯一區別在于,apply允許以數組的方式提供各個參數,而call方法必須一個一個參數的給。
前面的測試示例代碼中有多處運用到了這個方法。例如window對象并沒有hasOwnProperty方法,使用Object.prototype.hasOwnProperty.call(window, "propertyName")也可以測試它是否擁有某個本地屬性。

JavaScript中的閉包Closures
示例:

//Passed in FF2.0, IE7, Opera9.25, Safari3.0.4
function outer(){
    
var a="aaa";
    
var b="bbb";
    
return function(){ return a + " " + b; };
}
var inner=outer();
document.write(inner());

outer返回的是一個內嵌函數,內嵌函數使用了outer的局部變量a和b。照理outer的局部變量在返回時就超出了作用域因此inner()調用無法使用才對。這就是閉包Closure,即函數調用返回了一個內嵌函數,而內嵌函數引用了外部函數的局部變量、參數等這些應當被關閉(Close)了的資源。

 根據前面Scope Chain的理解可以解釋,返回的內嵌函數已經持有了構造它時的Scope Chain,雖然outer返回導致這些對象超出了作用域、生存期范圍,但JavaScript使用自動垃圾回收來釋放對象內存: 按照規則定期檢查,對象沒有任何引用才被釋放。因此上面的代碼能夠正確運行。


標簽:

本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@ke049m.cn

文章轉載自:博客園

為你推薦

  • 推薦視頻
  • 推薦活動
  • 推薦產品
  • 推薦文章
  • 慧都慧問
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
利記足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 真人boyu·博魚滾球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 最大網上PM娛樂城盤口(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規雷火競技官方買球(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 雷火競技權威十大網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) boyu·博魚信譽足球官網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 權威188BET足球網(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 正規188BET足球大全(官方)網站/網頁版登錄入口/手機版登錄入口-最新版(已更新) 国产精品成人啪精品视频免 | 国产精品偷伦免费视频观看的 | 国产爆乳美女呻吟娇喘在线播放 | 国产a级毛片久久久精品毛片 | 国产精品白富美sm调教三部曲 | 国偷自产av一区二区三区不卡 | 成人国产欧美 | 国产成人啪精品视频免费网站 | 国产午夜精品一区二区三区四 | 国产成人精品97 | 国产高清在线精品一区二区三区 | 国产在线911福利免费 | 国产女同毛片精品 | 国产欧美一级内射7乀 | 国产成人无码精品午夜福利a | 国产精品兄妹伦理片一区二区 | 99精品视频在线播放 | 91无码在线观看了 | 2025国产精品 | 精品国产美女在线一区二区三区 | 91成人精品国产一区 | 国产91av在线播放 | 国产一区二区三区亚洲 | 99久久综合狠狠综合久久最 | 国产在线欧美精品中文一区 | 国产成人综合日韩精品无码不卡 | 国产成人精品免费播放视频 | 国产精品视频无圣光一区 | 国产成人精品一区二区不卡 | 国产极品美女高潮无套在线 | 国产va在线观看免费 | 国产sm调教在线观看 | 激情啪啪精品一区二区 | 成人无码在线视频网站 | 成在人线av无码免费动态图 | 成人国产精品一区二区免费 | 成人午夜福利免费专区无码 | 国产午夜福利在线观看红一片 | 18禁裸体动漫美女无遮挡网站 | 二区三区漫画 | 国产精品一区二区剧情熟女 | 国产精品视频色综合网综合色 | 国产精品丝袜久久 | 国产成人精品月日本亚洲语音 | 国产熟女视频草草影院 | 国产无码高清 | 91精品啪在线 | 国产大学生无套内射 | 91精品婷婷色国产综合 | 91麻豆天美传媒在线 | 国产高清女同学巨大 | 国产爆白浆水真多视频 | 国产aⅴ熟女 | a级情欲片在线观看免费hd | 精品无码免费在线 | 国产精品成人麻烦视频 | 国产成人久久精品二区三区 | 2025久久精品国产免费 | 成人av鲁丝片一区二区免费 | 91久久久久精品无码∫ | 国产亚洲精aa在线观看see | 国产专区久久播放 | aⅴ在线观看视频 | 国产精品美女视频 | 国产免费无码av片在线观看不卡 | 国产精品欧美一区二区三区 | 成人动作片在线观看 | 国产中文字幕一级片在线观看 | 国产亚洲欧美另类在线第1页 | 国产成人人人97超碰超爽8 | 国产成人午夜精品一区二区三区 | 国产系列丝袜熟女精品网站 | 国产美女裸体无遮掩免费牛牛 | 99久久精品精品6精品精品 | 国产美女人喷水在线观看 | 国产在线观看91精品2025 | 国产精品国产三级国产aⅴ9色 | 国产91免费视频 | 国产aⅴ久久免费精 | 国产一区丝袜在线播放无弹窗 | 国产日韩久久久久精品影院 | 国产精品一区二区三区三洲欧洲 | 18禁黄网站禁片免费观看 | 大尺度做爰无遮挡动漫 | 国产一区鲁鲁在线视频免费播放 | 国产精品高清一区二区三区久久 | 国产蜜臀av在线一区尤物 | 国产99re6热在线播放 | 国产激情婷婷丁香五月天 | 国产成人精品免高 | 国产午夜成一人免费看片 | 二区三区妓女原神 | 按摩师舌头进去添的我好舒服 | 国产成人久久精品流白浆 | 国产女主播真实视频在线观看 | 国产一级片内射视频播放 | 国产成人片在线观看视频 | av每日更新 | 国产欧美精品专区一区二区 | 国产偷窥女洗浴在线观看潜入 | 国产午夜电影在线观看 | 精品一区二区三区不卡久久久 | 国产日韩欧美一区二区视频在线观看 | 岛国在线一区二区三区四区 | 高潮精品呻吟久久无码 | 精品国产午夜理论片不卡 | 91久久精品无码一级毛片 | 国产无码综合 | 国产av福利久久精品can | 国产成人久久精品二三区麻豆 | 国产精品乱人伦一区二区三区 | 丰满隔壁的女邻居 | 国产av国片精品麻豆 | 91精品国产91久久综合牛牛 | 精品少妇人妻一区二区黑料社 | 变态的让你无法想象 | 国产成人精品无人区一区 | 变态刺激另类sm孕妇 | 国产对白俱乐部交换在线播放 | 91精品视频免费看 | 成人色屋精品视频 | 国产无套视频在线观看香蕉 | 精品丝袜国产在线播放 | 国产精品亚洲一区二区在线观 | 精品无码a免费观看 | 国自产拍av在线天天更新 | 国产成人剧情av麻 | 91.www成人福利网站 | 国产精品成人一区二区三区视频 | 国产草草影院一区二区三区 | 18禁男女无遮挡啪啪网站 | 国产成人啪午夜精品网站男同 | 91久久香蕉国产熟女线看 | 91在线国产直播在线 | 国产成人欧美一区二区三区的 | 国产女午夜一区视频 | 国产美女精品91禁 | 国产精品无码毛片一区 | 国产精品毛片久 | 国产中文字幕免费 | av收藏夹| 国产一级无码av免费久久 | 精品国产一区二区三区免费91 | 国产精品一区二区日韩av | 韩国无码一区二区三区精品 | 国产中文字字幕乱码在线电影 | av亚欧洲日产国码无 | 国产无套内射一级毛片农民工 | 国产a一级黄片视频 | 国产熟女高潮精选视频 | 国产欧美日韩专区发布 | 国产一级av无码系列专区 | 99久久无码精品一区二区 | 国产成人精品女 | 按摩艳片一区区在线播放 | 99国产精品一区无码 | 国产成人午夜福利高清在线 | 激情人妻另类人妻伦 | 成人黄视频在线 | 国产欧美日产激情视频 | 1024中文| 国产精品一区二区在线观看99 | 国产精品国产三级国产av中文 | 国产成人三级视频在 | 国产内射在线激情一区 | 国产免费高清视频在线观看不卡 | 国内午夜免费鲁丝片 | 国产在线无码播放不卡视频 | 丰满巨臀大屁股bbw 丰满老熟妇aaaa片 | 国产精品制服丝袜亚洲欧美 | 91精品久久久久久久99蜜桃 | 潮喷失禁大喷水无码 | 国产精品白浆无码 | 国产av激情无码久久 | 国产片一区二区三区 | 国产午夜免费视频 | 国产成人精品久久一区二区三区 | 极品尤物日韩精品视频在线播放 | 精品日本三级在线观看 | 国内女子自慰喷潮a片免费观看 | 国产综合精品一区二区 | 成人午夜激情福利动态 | 成人在线观看av网站 | 成人欧美一区二区 | 国产精品大屁股白浆视频手 | 国产精品一区不卡在线观看 | 精品色网视频久久 | 91视频亚洲精品 | 国产日韩欧美女同一区二区 | 国产成人无码综合亚洲日韩 | 国产丝袜在线观看 | 国产精品无码专区免费不卡 | 精品视频在线免费观看 | 国产精品偷伦视频观看免费入 | 国产福利微拍精品一区二区 | 国产成人午夜福利在线观看视 | 国产一区二区三区免费精品 | 精品一区二区高清在线观看 | 国产高清在线精品一区免费 | 97色伦图片97综合影院久久 | 白嫩一区二区在线视频 | 国产高清天天看在线 | 91精品一区国产高清在线gif | 国产爆乳无码视频在线观看 | 国产高清精品福利私拍国产写真 | 国产三级高清视频在线观看 | 国产高清网站视频在线观看 | 国产成人免费精品在线观看 | 高清无码国产精品区 | 国产免费午夜福利蜜芽无码 | 国产三级在线电影 | 国产91精品久久久久999 | 国产成人综合精品一区 | 国产极品美女高潮无套在线 | av无码久久久久不卡免费网站 | 2025年国内精品视频 | 国产盗摄精品一区二 | 91精品久久国产青草 | 18禁无遮挡啪啪摇乳动态图 | 精品人妻av中文字幕乱码 | av天堂无码资源网 | 国产三级在线视频播放线 | 国产不卡视频一区二区三区四区 | 国产真实夫妇交换视频 | 国产成人综合精品亚洲 | 成人国产精品动漫欧美一区 | 2025免费国内精品在拍自线 | 国产精品成人无码 | av无码免费一区二区三区 | 国产毛片一区二区精品 | 91在线国自产拍 | 国产日韩一区二区在线观看 | 国产一区二区电影在线观看 | 国产精品一区二区三区三洲欧洲 | 91国偷自产一区二区三区蜜臀 | av天堂午夜精品一区二区三 | 丰满少妇高潮惨叫久久久一 | 91成人试看福利体验区 | 国产真实露脸多p视频播放 国产真实露脸精彩对白91 | 国产一区二区三区免费观看在线 | 国产盗摄精品一区二 | 国产成a人亚洲精v品无码樱花 | 国产超碰人人模人人爽人人添 | 国产欧美日韩一级视频在线观看 | 国产精品一区二区三区乱码中文字幕 | 2025国自产一点都不卡 | av每日更新手机观看 | 精品无码视频一区三区四区 | 91在线黄色视频 | 国产经典一区二区三区蜜芽 | 国产视频一区二区三区 | 国产丝袜在线观 | 国产精品三级高清在 | 国产爆乳美女娇喘呻吟在线观看 | 国产精品系列在线播放 | 国产亚洲欧美日韩综合一区 | a级毛片中文字幕完整版 | 国产一区久久 | 国产午夜福利电影免费在线观看 | 国产福利91精品一区二区三区 | 2025国产免费自拍视频 | 国产高清亚洲一区二区三区 | 国产白丝无码免费视频 | 国产日韩欧美一区二区视频在线观看 | 精品少妇人妻av一区二区三区 | 国产免费色视频 | 国产精品无码三级视频观看 | 超碰国产在线高清无码 | 精品国产高清一区二区久久91 | 精品国产一区二区三区四区特色 | 韩国无码一区二区三区精品 | 国产福利短片视频在线观看 | 国产一区二区激情视频在线 | 91热久久免费频精品动漫99 | 精品无码一区二区三区三十路 | 国产在线不卡人成视频 | 国产无码精品系列专区 | 动漫av成人无码精品网站 | 国产精品三p一区 | 岛亚洲品质网站入口 | 国产黄页网站视频在线观看 | 国产欧美日韩麻豆91 | 国产经典自拍一区 | 国产人妻人伦精品无码.麻豆 | 国产午夜福利最新在线观看 | 精品亚洲国产成人av网站 | 国产av巨作情欲放纵无码 | 国产制服日本一区二区 | 国产综合精品中文第一 | 91久久精品无码一级毛片 | 国产精品无码无卡毛片不卡 | 精品一区二区高清 | 国产成人亚洲精品乱码在线观看 | 精品国产仑片一区二区三区 | 国产一区二区三区日韩精品欧美 | 精品久久久久久天美传媒 | 国产成人综合五月天久久 | 国产欧美日本一区二区三区免费 | 精品亚洲高清一区二区三 | 国产白浆在线 | 国产aⅴ无码专区亚洲av综合网 | 国产白嫩漂亮美女在线观看 | 国产精品思思热在线 | 国产精品一区二区三区高清在线 | 国产精品亚洲精品青 | 精品国产品国语在线不卡 | 91亚洲精品福利在线播放 | 国产精品一区电影 | 国产美女极度色诱视频www | 国产精品视频一区二区三区在线观看 | 国产一区二区三区不卡在线观看 | 精品久久全免费的听书软件 | 国产真实高潮太爽了十八 | 91黄色视频 | 国产精品高潮69情节跌宕起伏 | 成人亚洲a片ⅴ一区二区三区动漫 | 国产精品福利在线播放 | 91福利国产在线 | www亚洲天堂 | 成人h动漫精品一区二区无 成人h动漫精品一区二区无码 | 国产精品无码一级毛片app下载 | 国产寡妇偷人在线视频 | 国产成人综合亚洲不在线 | 国产日韩aⅴ免费无码一区二区 | 福利一区在线视频 | 国产日韩精品欧美一区灰 | 成人午夜免费无码福利软件 | 国产成人综合久久亚洲精品 | 国产一级毛片久久久久久 | 国产黑色丝袜在线观看下 | 国产午夜福利精品久久2025 | 国产尤物高清 | av无码精品一区二区三区四 | 91国偷自产中文字幕婷婷 | 国产精品99无码一区二区 | 国产熟睡乱子伦视 | 国产aⅴ无码精品一品二区 国产aⅴ无码精品一区二区 | 99九九视频高清在线 | 99久久精品国产麻豆 | 国产成人精品一区二区三区不卡 | 国产喷水自慰在线观看 | 精品人妻一区二区三区浪 | 91九色视频在线观看 | 国产成人亚洲精品无码a大片 | 精品国产自线午夜福利在线观看 | av无码国产精品色午夜 | 国产成人无码午夜视频在线播放 | 国产高清在线观看视 | av无码一区二区三区鸳鸯影院 | 2025国产精品自拍视频 | 国产成人精品综合久久66 | 9191精品国产免费久久 | 国产自愉自愉免费精品 | 国产真实乱人偷精品人妻 | 91无码人妻丰满熟妇区五十路 | 精品无码av一区 | 国产探花在线精品一区二 | 国产精品无码av一区二区三 | 国产盗摄女厕美女嘘嘘 | 国产麻豆精品免费密入 | 国产一级av不卡毛片 | 精品无码一区二区三区不卡 | 大尺度做爰床戏呻吟的视频网 | 国产麻豆剧传媒精品网站 | 国产精品无码色一区二涩欲区三区 | 国产成人自拍视频 | 9191在线 | 成a人片在线观看中文漫画 成a人无码午夜电影 | 国产a级毛片久久久精品毛 国产a级毛片久久久精品毛片 | 精品国产中文自拍 | 精品人妻大屁股白浆久久 | 成人国内免费精品视频在线观看 | 国产成人18黄网站在线观看 | 91啪国自产在线高清观看 | 99精品国产高清一区二区三 | 国产成人免费高潮激情视频 | 成人亚洲国产精品无码久久一线 | 国产成人精品亚洲日本在线 | 国产午夜无码片在线观看影视 | 国产在线精品国自产拍影院 | 国产互换人妻好紧hd无码 | 成人午夜精品网站在线观看 | 白丝美女视频 | 国产99久久久国产精品成人 | 国产无套粉嫩白浆免费观看 | 国产av天堂亚洲国产av麻豆 | 国产一级久久毛片 | 国产成人午夜精品影院 | 变态调教无码专区在线观看 | 国产精品多人p群无码 | 精品人妻一区二区三区四区在线 | 爆乳国产中文在线观看 | 国产午夜激无码 | 国产精品成人免费精品自在线 | 动漫av永久无码精品每日更新 | 国产在线无码精品麻豆不卡 | 国产丝袜视频在线观看 | 91麻豆精品欧美视频 | 91成人爽a毛片一区二区动漫 | 国产成人92精品午夜福利 | 精品久久久久久中文字幕无码软件 | 国产无码精品在线 | 2025午夜福利网站入 | 91黄色视频免费在线观看 | 国产欧美日韩一区二区刘玥 | 国产美女裸身无遮挡网站 | 国产午夜毛片v一区二区三区 | 国产av夜色一区二区三区 | 国产精品毛片在线 | 国产高清特黄无遮挡大片 | 国产成人午夜性a一级毛片 国产成人午夜一区二区 | 国产精品va在线观看丝瓜影院 | 国产av无码专区亚洲av琪琪 | 国产一区二区三区在线观看视频 | 国产成人av在线你懂的 | 精品人妻无码一区二区三区99 | 国产成人精品aa毛片 | 成人午夜一区二区三区视频 | 国产精品视频第一页 | 高潮喷水无码一 | 国产成人久久精品一区二区三区 | 极品女神白富美露脸啪啪 | 国产精品九九一区视频 | 国产av无码精品麻豆 | av站天堂资源网 | 精品无码免费专区毛片 | 精品午夜福利无人区乱码一区 | 69久久久a片无码国产精 | 69国产精品成人在线播放 | 精品日韩丝袜在线 | 91桃色午夜福利国产在线观看 | 国色天香久久精品国产一区 | 国产成a人亚洲精v品在 | 国产脚交视频在线观看 | 激情亚洲精品中文字幕 | av天堂精品久久久久 | 国产精品大片大片看大 | 18禁无遮挡无码网站免费 | 国产一区在线主播中文 | 国产精品一区二区四区 | 国产操逼视频免费看 | 国产精品国产三级国av中文 | 国产成人手机在线视频在线观看 | 国产91丝袜在线播放动漫 | 国产午夜无码喷水福利在线观看 | 国产午夜精品自在自线之la | 成人欧美一区二区三区黑人免费 | 国产无码高清 | 国产精品一级毛片无码 | 99久久婷婷国产自综合青草 | 国产成人精品亚洲午夜麻豆 | 精品亚洲一区二区三区在线播 | 国产高清专区免费资源网站 | 爆操欧美美女 | 国产黄色一级精 | 东京热无码一区二区免费不卡 | 2025国产麻豆剧传媒电影 | 高潮激情视频 | 69成人免费视 | 国产爆乳无码在线观看 | 国产高清女同学巨大乳在线 | 国产高清不卡二区免费视频 | 国产精品v毛片免费看视频 国产精品v毛片免费软件 | 国产白领诱惑在线观看 | 国产午夜精品理论片久久影院 | 国产午夜成人无码免费 | 国产一线视频在线看 | 国精视频一区 | 国产精品伦理在线 | 国产激情久久久久久老熟女影视 | 18禁免费无码无遮挡 | 国产午夜高清高清在线观看 | 国产成人麻豆精品午夜福利在线 | 国产精品一级a∨片免费看 国产精品一级aa片 国产精品一级av在线播放 | 国产精品制服一区二区 | 国产午夜激无码av毛片护士 | 精品无码一区二区三区电影婷婷 | 国产蜜芽尤物在线一区 | av在线亚洲男 | 国产成人av在线亚洲天堂在线观看 | 91久久久久精品 | 国产午夜福利在线播放 | 国产成人啪精品午夜在线观看 | 国产成人综合久久精品推下载 | 成人深夜福利在线播放不卡 | 国产高清免费视频免费观看 | 国产精品一线二线三线四线毛片 | 成人免费又黄又爽视频 | 国产精品v日韩精品v | 国产精品无码一区二区在线观一 | 囯产精品一区二区三区线 | 国产午夜精品一区二区三区不卡 | 99精品视频免费热 | 国产精品一线二线三线品牌 | 国产成人av区一区二区三 | 99久久人妻无码精品系列 | 国精产品一线二线三线网站 | 国产精品一级a∨片免费看 国产精品一级aa片 国产精品一级av在线播放 | 91精品一区二区三区在线观看 | 国产精品午夜福利电影 | 国产激情视频一区二区三区 | 国产内射大屁股白浆一区二区 | 91视频直播app| 国产精品欧美精品国产主播 | 精品国产v无码大片在线观看视色 | 国产黄在线观看免 | 国产欧美日韩中文在线观看不卡 | 97人妻碰碰碰久久久久禁片 | 国产精品亚洲专区无码破解版 | 国产三级理论片 | 精品国产乱子伦一区二区三区58 | 国产高清免费不卡观看 | 国产精品日产无码av永久不卡 | 精品国产一区二区三区性色a∨ | 国产精品丝袜亚洲熟女 | 寡妇高潮一级毛片在线播放一 | 国产精品亚洲综合色区韩国 | 国产猛男猛女超爽免费色网视频 | 成人精品在线免费观看 | 国产精品国产三级国产av | 国产精品一区二区国模私拍 | 成人自拍视频在线观看 | 国产丝袜一区 | 丰满熟妇乱又伦在线无码视频 | 国产午夜精品一区二区三区不卡 | 国产制服丝袜你懂的 | 91午夜福 | 国内外精品激情刺激在线 | 国产在线a不卡免费视频 | 国产欧美日韩另类va在线 | 国产精品高潮丝袜无码 | 国产成人综合野草 | 国产成人一区二区三区视频免费 | 国产野战无套av毛片 | 国产精品亚洲第一区二区三区 | 国产精品高清一区二区不卡乱 | 成人国产视频在线 | 91亚洲精品自 | 国产高清视频在线观看69 | 国产高清无码一v二v | 国产午夜精品理论片 | 国产a级三级三级三级 | 91午夜在线免费观看小视频 | 国产精品一级无码视频播放 | 国产91丝袜在线播放 | 国产a级毛片免费视频一区二区 | 国产成人观看在线视频 | 国产年轻女教师a级毛片 | 国产精品美脚玉足脚交欧美 | 国产高清中文字幕欧美 | 18禁漫画在线 | 国产精品入口麻豆午夜 | 成人无码免费午夜福利在线看片 | av一区二区 | 国产精品日日摸夜夜添夜夜添 | 国产尤物视频免费看 | 97无码人妻福利免费公开在 | 国产精品盗摄一区二区在线 | 国产精品无码一区免费看 | 国产精品一区二区午夜嘿嘿嘿小说 | 国产熟女视频草草影院 | 国产一区二区三区不卡在线看 | 91网红福利精品区一区二 | 国产a级毛片久久久毛片精片 | 国产午夜91福利一区二区 | 精品人妻午夜一区二区三区 | 91偷拍一区二区三区精品 | 国产丝袜一区二 | 91国自产拍精品 | 国产精品高清一区二区三区 | 国产在线精彩视频二区 | 国产精品原创中文巨作av | 加勒比精品久久一区二区三区 | 91精品云霸高清中文字幕 | 国产成人一区二区三区电影 | 国产精品成人自拍 | 国产成人精品免费视频大全麻豆 | 国产欧美丝袜小视频 | 国产成人最新毛片基地 | 国产福利姬精品福利 | 成人精品午夜无码 | 国产一区二区无码专区 | 国产成人a国产在线观看 | 成人精品视频一区二区三区 | 国产成年人免费黄色视频 | 国产桃色无码在线播放一区 | 国产激情视频在线观看 | 国产成人一区二区三区 | 精品国产av色一区二区 | 国产高级会所按摩技师在线看 | 国产在线永久免费 | 国产精品多p对白交换绿帽 国产精品多人p | 精品少妇无码v无码专区 | 精品国产精品国自产观看 | 91精品福利一区二区三区 | 国产三片理 | 白丝乳交内射 | 国产成人精品高清在线观 | 观看欧美一区二区三区 | 精品国产9999一区二区三区 | 国产后式视频无码在线 | 国产一区二区在线日韩 | 精品国产高清自在线看 | 高清无码一区二区在线观看 | 国产91福利小视频在线观看 | 91尤物视频在线观看 | 91精品视频在线观看一区 | 东京热加勒比无码少妇 | 国产在线播放综合网房 | 99精品国产免费观观 | 成人国产欧美精品一区 | 丰满的少妇69式视频在线观看 | 国产精品一二三在线观看 | 国产精品一区99国产aaa精 | 国产97免费视频在线观看 | av免费无码天堂在线 | 成人毛片无码免费播放网站 | 国产成人无码aⅴ片在线观看 | 91popr国产在线观看 | 18禁黄网站禁止免费观看 | 国产精品美女久久久久久麻 | 国产欧美高清一区二区三区 | 国产成人精品久久一 | 成人午夜福利视频 | 精品日本一线二线三线区别在 | 国产精品国产三级国产αv 国产精品国产三级国产成人 | 国内精品久久人妻无码妲己 | 国产精品国产免费无码专区不 | 国外免费人妖网视频在线观 | 18禁无遮挡羞羞啪啪免费网站 | av喷水高潮喷水在线观看 | 成人精品高清视频在线观看 | 国产在线视频二区不卡 | 岛国av无码不卡一区二区三区 | 国产精品无码久久久久久 | 国产在线精品一区二区在线观看 | av无码精品一区二区三区 | 精品亚洲av无码国产一二区在线 | 精品视频高清在线观看 | 白嫩无码人妻熟妇啪啪区 | 精品国偷自产在线视 | 国产高清超清在线播放 | 国产粗口调教在线播放 | 国内拍自产精品视频在线观看 | 成人在线精品视 | 精品国产一区二区三区蜜桃 | 国产精品视频一区二区噜噜 | 国精产品一区二区三区 | 成人无码国产电影 | 国产午夜精品久久久久九九电影 | 91精品国产手机 | 精品亚洲欧美高清不卡高清 | 国产爆白浆水真多视频 | 国产成人免费高清直播软件 | 国产毛片久久久久久国产毛片无码 | 成人国产一区二 | 国产一区二区免费视频 | 成人午夜福利 | 18禁无遮挡羞羞污污污污网站 | 激情视频在线观看一区 | www国产成人免 | 精品无码v免费 | 国产精品白浆无码流出系列视频 | 韩国无码无遮挡在线观看不 | 国产成人永久在线播放 | 高h猛烈失禁潮喷a片在线播放 | 国产麻豆剧传媒 | 国产不卡三级在线播放 | 国产二区三区在线观看视频 | 国产精品成人网址在线观看 | 国产一区二区三区成人欧美日韩在 | 寡妇高潮一级毛片免费看 | 精品精品国产自在97香蕉蜜芽 | 成人免费www在线高清观看 | 成人国产片视频 | 国语对白嫖老 | 国产超碰人人爽人人做人人添 | a级全黄试看30分钟国产 | 国产综合一千收藏 | 99精品偷拍视频一区二区三区 | 精品国产尤物一区二区三区 | 国产精品成人一区二区不卡 | 国产天堂一区二区三区 | 国产成人午夜 | 国产一区精品一区无码 | 国产欧美日韩中文久久 | 国产乱xxⅹxx国语对白 | 91精品国产制服啪啪无码 | 91精品综合在线视频 | 国产色婷婷精品综合在线播放 | 国产成人无码av在线播放动漫 | 成年永久一区二区三区免费视频 | 国产午夜福利精品偷伦91 | 2025国产成人精品视频人 | 国产av午夜精品一区二区入口 | 国产精品成人久久 | 不卡日韩在线精品二区 | 国产最猛性xxxxxx69交 | 国产精品天干天干在线观看 | 国产成人精品三级在 | 国自产精品手机在线 | 国产麻豆日韩欧美久久 | 国产欧美国日产高清视频 | 99久久精品美女高潮噴水 | 国产精品原创巨作av | 岛国无码av潮喷 | 精品人妻一区二区三区声综 | 国产丝袜视频一区二区三区 | 99精品久久久久久久婷婷 | 国产不在线观看精品一区免费 | 国产精品无码制服丝袜 | 国产一区二区免费视频 | 国产真人一级a爱视频免费看 | 高清无码一区二区在线观看吞 | 国产午夜激无码av毛片护士 | 国产一区二区三区秘 | 国产成人精品a视频 | 久久精品无码一区二区毛片 | 国产美女久久久久久久久久久 | 2025最新电视剧高清热播 | 国产在线精品成人一 | 国精产品自线在拍在线精品 | 国产av影片麻豆精品传媒 | 国产精品久久久久一区二区三区 | 国产精品精品系列在线观看 | 风流老熟女一区二区三区 | 国产精品99无码一区二区 | 99国产精品白浆无码流出 | 国产熟女视频一区二区免费 | 97色伦午| 国产高清在线精品二区app | 国产精品亚洲欧美高清 | 国产日韩av免费无码一区二区三区 | 91成人影院在线观看 | 国产高清不卡一二三区 | 国产精品三级手机在线观看 | 国产美女裸舞久久福利 | 91久久久 | 国产一区欧美日韩另类 | 国产白嫩美女 | 国产免费高清国产在线视频 | 二区久久人人澡 | 91久久国产综合久久91大便 | 国产精品va欧美精品v日韩 | 国产成人精品高清国产三级 | 精品精品国产欧美在线观看 | 精品亚洲一区二区不卡 | 国产私密网站入口 | 91一区二区午夜免 | 国产白袜| 国产情趣免费视频在线观看 | 国产精品亚洲第一页 | 国产午夜无码片在线观看影视 | 精品国产一区二区三区色欲 | 极品国产在线观看 | 丰满多水的寡妇 | 91一区二区在线观看精品 | 国产精品成人无码久久久久久 | 国产一区二区三区三区 | 国产在线观看一区免费精品 | 精品国产自产自在 | 国产高清av在线播 | 精品视频免费观看 | 国产精品嫩 | 按摩已婚人妻精品中文字幕 | 东京无码熟妇人 | 91久久| 国产成人精品久久久久精品 | 精品人妻少妇嫩草av无 | 国产一区高清视频在线观看 | 精品一区二区三区东京热 | 国产午夜福利白浆一区二区 | 国产福利在线观看日本二区三区 | 国产美女口爆吞精系列 | 国产成人尤物在线视频 | 东京日韩人妻无码专区一本亚州最新 | 国产成人综合一区精品 | 91精品国产品国语在线不卡 | 国产精品亚洲欧美高清亚洲综合欧 | 国产在线视频国产永久视频 | 国产成本人片无码免费2025 | 国内偷自第一区二区三区 | 国产成人精品亚洲精品 | 国产精品一区12p | 国产成人三级在线播放 | 精品日韩在线视频一区二区三 | 国产一二三四精品久久 | 国产成人av剧情自拍网站 | 成人无码av一区二区三区 | 国产亚洲欧美日韩在线观看一区 | 国产激情精品一区二区三区 | 国产黄色电影在线观看 | 国产精品午夜无码av体验区 | 国产精品爆乳奶水 | 国产精品麻豆视频网站 | 精品久久九九九久久久久国产 | 91亚洲国产成人久久精品 | 国产成人啪精品视频免费网站 | 国产一区在线观看 |