javascript Object分析

ForTechnology發表於2011-08-05
javascript. Object分析[問題點數:40分,結帖人:baibaidudu]
•    
•    baibaidudu
•    (baibaidudu)
•    
•    等 級:  
•    結帖率:60.00%•        樓主發表於:2010-06-09 20:54:55
接著前面的javascript. 的資料型別分析說下object的分析:
 Object
除了5種原始型別外,一切都是Object,包括Object、Function、Array等等,他們的例項和構造器,都是Object。那Object是一個什麼東西呢?  
Object是一個:無序的成員集合  
它是一個集合,說明它包含0-n個成員。而它是無序的。  
每一個成員由以下3個部分組成:名稱、值、特徵集合  
下面的程式碼中:  
var bj = {'key': 'value'};  
key就是成員名稱,value就是值,obj這個Object從程式碼上看起來包含了一個成員,注意,是從程式碼上看而已。這裡我們不去深究它先。  
那特徵集合是個什麼東西呢?
javascript的物件成員可能包含下面幾種特徵的0個或多個:ReadOnly、DontEnum、DontDelete、Internal。  
• ReadOnly:擁有這個特徵的成員是不能被程式修改的。  
• DontEnum:擁有這個特徵的成員是不能被for in遍歷的。  
• DontDelete:擁有這個特徵的成員是不能被delete操作刪除的。  
• Internal:代表這個成員是內部成員。通常內部成員不能被程式以任何方式訪問,但是有些javascript的引擎實現將它以特殊方式暴露,使得可以訪問物件的某些內部成員。  
一個物件的Internal成員以[[xxxx]]的方式來表示。  
下面列一些和本博有關的的Object可能包含的internal成員。  
• [[Class]]:表示該物件的型別。比如function Object的[[Class]]成員的值是"Function"  
• [[Get]](PropertyName):獲取物件的屬性值。  
• [[DefaultValue]] (Hint):用於ToPrimitive進行型別轉換時呼叫。hint引數可能的值為"string"或"number"  
• [[Prototype]]:[[Prototype]]成員實現了javascript中所謂的“原型鏈”。一個物件的[[Prototype]]成員可能是object物件,或者是null。只有Object.[[prototype]]為null,其他任何物件的[[Prototype]]成員都是一個Object  
• [[Call]]:function Object特有的成員,在函式被呼叫的時候,就是呼叫的[[Call]]。  
• [[Construct]]:function Object特有的成員,在函式作為構造器,被new操作符用於建立物件的時候,就是呼叫的[[Construct]]。  
• [[Scope]]:[[Prototype]]成員實現了javascript中所謂的“作用域鏈”。  
5. function Object的建立過程
解析器在遇到function declaration或者function expression的時候,會建立一個function Object。步驟大致如下:  
1. 解析形參和函式體  
2. 建立一個native ECMAScript. Object:F  
3. 設定F的[[Class]]、[[Prototype]]、[[Call]]、[[Construct]]、[[Scope]]、length屬性  
4. 建立一個new Object():O  
5. 設定O的constructor屬性為F  
6. 設定F的prototype屬性為O  
在這個建立過程裡,要說明的幾點是:  
1. 步驟3中F的[[Prototype]]被設定為Function.prototype  
2. 使用者自定義的function,都會同時具有[[Call]]和[[Construct]]這兩個internal屬性  
3. 解析器會自動給每一個function Object初 始化一個prototype成員。而F.prototype.constructor == F,所以,當我們沒有重新定義這個F的prototype成員的時候,F的例項的constructor成員是靠譜的。因為(new F).constructor其實方位的是F.prototype.constructor,而解析器預設初始化給你的 F.prototype.constructor就是F。  
4. 關於[[scope]]和作用域鏈的問題,下文分解  
還要提的一點是,function declaration和function expression是不一樣的  
function declaration:  
function fn() {}  
function expression:  
var a = function () {};  
function () {};  
6. 原型鏈
首 先要澄清的一點是,我們通常會使用myfunction.prototype的方式進行原型擴充套件,所以我們在聽到“原型鏈”這個詞的時候,會覺得這裡的 “原型”指的是myfunction.prototype。其實不是,“原型”指的是物件的[[Prototype]]。當然,物件的 [[Prototype]]就是其真實構造器當前的prototype成員物件。  
上文中有提過,一個我們通過程式建立的function Object,一定會包含[[Call]]和[[Construct]]這2個internal成員。它們做了什麼事情呢?  
[[Call]]:  
1. Establish a new execution context using F's FormalParameterList, the passed arguments list, and the this value as described in 10.2.3.  
2. Evaluate F's FunctionBody.  
3. Exit the execution context established in step 1, restoring the previous execution context.  
4. If Result(2). type is throw then throw Result(2). value.  
5. If Result(2). type is return then return Result(2). value.  
6. (Result(2). type must be normal.) Return undefined.  
[[Construct]]:  
1. Create a new native ECMAScript. object.  
2. Set the [[Class]] property of Result(1) to "Object".  
3. Get the value of the prototype property of F.  
4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).  
5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.  
6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.  
7. If Type(Result(6)) is Object then return Result(6).  
8. Return Result(1).  
一切都很清楚了。當我們建立一個物件,也就是我們new的時候,呼叫的是function Object的[[Construct]]成員方法。在上面的描述中,3、4步描述了[[Prototype]]成員的建立過程,就是構造器的prototype成員。  
好的,那回到之前,我們使用obj.property來獲取obj物件的屬性的時候,其實呼叫的是obj物件的internal方法[[Get]]。那我們看看[[Get]]方法呼叫做了哪些事情:  
1. If O doesn't have a property with name P, go to step 4.  
2. Get the value of the property.  
3. Return Result(2).  
4. If the [[Prototype]] of O is null, return undefined.  
5. Call the [[Get]] method of [[Prototype]] with property name P.  
6. Return Result(5).  
可 以看出來,當我們獲取物件obj的某個成員的時候,會在obj物件自身成員裡查詢是否存在該成員。如果不包含,則到obj.[[Prototype]]這 個物件中查詢名字成員,如果還不存在,則到obj.[[Prototype]].[[Prototype]]這個物件裡找,直到某個 [[Prototype]]是null為止。查詢的過程就是一個順藤摸瓜的事情,這個藤就是我們所謂的“原型鏈”。  
我不想說太多原型鏈和繼承之間的關係與實現,這方面的資料在網路上已經太多太多。我只想把原型鏈脫光了告訴大家,原型鏈是什麼。  



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-704297/,如需轉載,請註明出處,否則將追究法律責任。

相關文章