ECMA262 Edition5 Object,Object的属性和方法,Object.prototype的方法.
ES5,為Object添加了一批方法.了解這些方法,可以更好的理解屬性描述符的應用. 所以還是很有必要讀一讀的。另外,這些方法用起來還是蠻給力的.
暫時對于ES5,就只放出這些吧,希望對大家有所幫助. ?此部分大量提到類似 [[getOwnProperty]]等部分可以參考 :http://www.cnblogs.com/_franky/articles/2143688.html
閱讀幫助:
如果格式難以閱讀,請您諒解,因為copy自evernote.排版很糾結. 您可以選擇:
1. 換一個足夠寬的顯示器
? ? ? ?2. 調高分辨率
? ? ? ?3. 縮小瀏覽器文字尺寸.?
15.2 Object對象.
??
15.2.1 把Object構造器,當做一個函數來調用 當 Object 當做一個函數,而不是作為一個構造器來調用,就會發生個類型轉換操作.? ? ?15.2.1.1 Object([value]);(作為函數調用,其實拋開宿主對象,行為和 new Object沒啥區別)
當 Object作為函數,以無參或以value作為參數調用時,就按下面的步驟進行操作: 1. 如果 value是 null,或undefined 或沒有傳參,就如同以相同參數,去使用內置的Object構造器一樣,創建并返回一個,new Object. 2. 返回 ToObject(value).? ? ?15.2.2 Object構造器
當Object作為構造器,以無參或以value作為參數.被調用時,就按下面的步驟進行操作: 1. 如果傳遞了參數,則 a. ?如果 Type(value) 是 Object,則 i. ?如果 value是一個原生(native)ECMAScript對象,就甭創建新的對象了.直接返回value. ii. ?如果 value是一個宿主對象,那么其行為就是依賴于這個宿主對象相關的具體實現的.(就是說,返回啥.由宿主環境看著辦了.) b. ?如果 Type(value)是 String,則返回 ToObject(value). c. ?如果 Type(value)是 Boolean,則返回 ToObject(value). d. ?如果 Type(value)是 Number,則返回 ToObject(value). 2. 優點:當參數沒有傳遞參數value,或者它是null或undefined的情況下. 3. 令obj 為一個新創建的ECMAScript 對象.(new Object) 4. 設置obj的內部屬性[[Prototype]]為內置對象 prototype. 5. 設置obj的內部屬性[[Class]]為'Object'. 6. 設置obj的內部屬性[[Extensible]]為 true. 7. 把那些在8.12章節定義的內部方法,都添加給 obj. 8. 返回obj.屬性:
? ? ?15.2.3 Object構造器的屬性
Object的內部屬性[[Prototype]],是內置對象Function.prototype對象. 還有一個 ?值為1的內部屬性 length(函數對象的形參個數.), 剩下的就都是它滴對外開放滴屬性了.? ? ?15.2.3.1 Object.prototype
Object.prototype的初始化值是內置對象 prototype.(參考15.2.4),這個屬性的特性是這樣滴:{[[Writable]]:false,[[Enumerable]]:false,[[Configurable]]:false}.?
靜態方法:(所有靜態方法,都是ES5新增的東東.)
? ? ?15.2.3.2 Object.getPrototypeOf(O)(獲取參數對象的內部屬性 [[Prototype]])
當以O作為參數調用 getPrototypeOf方法時,就按下面的步驟進行操作: 1. 如果?Type(O) 不是Object,(或者O是null,原文疏漏了.因為Type(null)也是 Object后面幾個方法亦如此.不再解釋.)?則拋出一個 TypeError異常. 2. 返回 O的內部屬性[[Prototype]].? ? ?15.2.3.3 Object.getOwnPropertyDescriptor(O, P)
?????(獲取指定對象的,屬性描述符的ECMAScript對象.就像這樣子:{value:123,writable:true,enumerable:false,configurable:true}) 當以O, P,作為參數,調用getOwnPropertyDescriptor方法時,就按下面的步驟進行操作: 1. 如果Type(O) 不是Object, 或者O是null, 則拋出一個TypeError異常. 2. 令 name 為 ToString(P).的結果. 3. 令 desc為以 name為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. 4. 返回調用 FromPropertyDescriptor(desc)的執行結果(一個可以描述屬性特性集的ECMAScript 對象.參見 8.10.4)? ? ?15.2.3.4 Object.getOwnPropertyNames(O)(獲取指定對象的所有自身獨占屬性名,包括不可枚舉的.并返回一個數組.)
當以O作為參數調用getOwnPropertyNames方法時,就按下面的步驟進行操作: 1. 如果?Type(O) 不是Object, 或者是null,就拋出一個TypeError異常. 2. 令 array 為 借助表達式 new Array()創建的一個新對象, Array就是那個叫做Array的內置構造器(說實話,翻譯的時候很有壓力.廢話連篇.但為了精準,避免歧義.也是木有辦法.). 3. 令 n 為0. 4. 迭代每一個O獨占(自身)屬性 為P.(此迭代是,無視該屬性是否可枚舉的.只要有O自身有的屬性.就要枚舉出來) a. ?令 name 為 P的字符串值. b. ?以ToString(n),屬性描述符{[[Value]]:name,[[Writable]]:true,[[Enumerable]]:true,[[Configurable]]:true},false作為參數,調用 array的內部方法[[DefineOwnProperty]]. c. ?n自增1. 5. 返回 array. 注意如果 O 是一個String的實例,處理到第四步的時候.還要包含那些在 15.5.5.2章節中定義的那些隱式屬性(注1).也就是O的[[PrimitiveValue]]字符串,所對應的字符串們.(還有length.)? ? ?15.2.3.5 ?Object.create(O [, Properties])(創建一個對象,并把該對象的[[Prototype]]設置為O.同時可以一次性添加n多屬性)
create方法根據指定的 prototype去創建一個新對象. 當create方法被調用時,就按下面的步驟進行操作: 1. 如果 Type(O) 不是Object,則拋出一個TypeError異常. 2. 令 obj 為 new Object(),(不直譯了。原文就是這個意思.太羅嗦.) 3. 把 obj的內部屬性[[Prototype]]設置為 O. 4. 如果傳遞了參數 Properties,并且值不是 undefined, 就像調用內置方法 Object.defineProperties那樣把指定的屬性添加給obj. 5. 返回 obj.? ? ?15.2.3.6 Object.defineProperty(O, P, Attributes)(為制定對象,根據指定特性集,添加或設置一個屬性)
defineProperty方法,是用于為一個對象添加或修改一個自身屬性獨占屬性的.當它被調用,就按照下面的步驟進行操作: 1. 如果 Type(O)不是Object,或者O是null,則拋出一個TypeError 異常. 2. 令 name 為ToString(P)的值. 3. 令 desc 為 以 Attributes為參數,調用 ToPropertyDescriptor 的運算結果.(obj 轉 屬性描述符) 4. 以name,desc,true 為參數,調用 O的內部方法[[DefineOwnProperty]]. 5. 返回O.? ? ?15.2.3.7 Object.defineProperties(O, Properties)
?????(可以理解成,Properties是一個包含一系列屬性名的對象,這些屬性名的值都是特性集對象.然后批量的進行defineProperty操作.) defineProperties方法,是用于批量的,為一個對象,添加或修改某些自身獨占屬性的.當它被調用,就按照下面的步驟進行操作: 1. 如果 Type(O)不是Object,或者O是null,則拋出一個TypeError 異常. 2. 令 props 為 ToObject(Properties). 3. 令 names 為一個包含 props所有可以枚舉的自身獨占屬性名的 內部 list對象(參考8.8章節). 4. 令 descritpors 為一個空的內部 list對象. 5. 按照 names list的順序去迭代每一個 ?names中的元素,作為P. a. ?令 descObj 為,以P為參數,調用 props的內部方法 [[Get]]的返回值. b. ?令 desc 為,以 descObj為參數,調用 ToPropertyDescriptor的執行結果.(把obj轉屬性描述符) c. ?把 desc添加到 descriptors上. 6. 按 descriptors list的順序去迭代每一個 desc元素, a. ?以P,desc,true 作為參數,調用O的內部方法[[DefineOwnProperty]]. 7. 返回 O.? ? ?15.2.3.8 Object.seal(O)
?????(把指定對象,設置為密封狀態,即使對象不可擴展.且所有自身獨占屬性,都不可刪除,而且,類似seal,freeze等方法.操作特性時,是無視其屬性原始的Configurable的.無論如何都有權限) 當seal被調用,就按照下面的步驟進行操作: 1. 如果 Type(O)不是Object,或者O是null,則拋出一個 TypeError異常. 2. 迭代每一個O的自身獨占屬性名.屬性名作為P的值(Object的這些批量操作屬性特性的方法,所指的迭代,都是不考慮其是否是可枚舉的.語義上來說,這樣才是合理的) a. ?令 desc 為 以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. b. ?如果 desc.[[Configurable]] 是true,把 desc.[[Configurable]]設置成,false. c. ?以 P,desc,true 作為參數,調用O的內部方法[[DefineOwnProperty]].\ 3. 把 O 的內部屬性[[Extensible]]設置為false. 4. 返回 O.? ???15.2.3.9 Object.freeze(O)
?????(把指定對象,設置為凍結狀態,即使對象不可擴展.且所有自身獨占屬性,都不可刪除的同時,如果任何一個屬性是數據屬性,則將該屬性的[[Writable]]特性設置為false.) 當freeze方法被調用,就按下面的步驟進行操作: 1. 如果 Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 迭代O的每一個屬性,屬性名作為P的值. a. ?令desc 為以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. b. ?如果 isDataDescriptor(desc)是true,則(注2) i. ?如果 desc.[[Writable]]是true,則把 desc.[[Writable]] 設置為false. c. ?如果 desc.[[Configurable]] 是true, 則把 desc.[[Configurable]] 設置為false. d. 以 P,desc,true 為參數調用 O的內部方法[[DefineOwnProperty]]. 3. 把O的內部屬性[[Extensible]]設置為false. 4. 返回O.? ? ?15.2.3.10 Object.preventExtensions(O)(就干一件事,把指定對象的內部屬性[[Extensible]]設置為false,使指定對象為不可擴展狀態.)
當 preventExtensions方法被調用,就按下面的步驟進行操作: 1. 如果 Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 把O的內部屬性[[Extensible]]設置為false.? ? ?15.2.3.11 Object.isSealed(O)(判斷某對象是不是密封的,如果一個對象是凍結的,那么它也一定是密封滴.)
? ? ?當以O為參數,調用isSealed方法時,就按下面的步驟進行操作: ? ? ?1. 如果 Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 迭代O的每一個自身獨占屬性,名為P. a. ?令desc為以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. b. ?如果desc.[[Configurable]] 為true,則 返回false. 3. 如果O的內部屬性[[Extensible]]為 false.,則返回true. 4. 其他情況 返回false.? ? ?15.2.3.12 Object.isFrozen(O)(判斷某對象是不是凍結狀態,即所有自身屬性不可編輯,所有數據屬性都只讀,且該對象不可擴展.)(注3)
? ? ?當以O為參數,調用isFrozen方法時,就按下面的步驟進行操作: ? ? ?1. 如果 Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 迭代O的每一個自身獨占屬性,名為P. a. ?令desc為以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. b. ?如果isDataDescriptor(desc)是true,則 i. ?如果 desc.[[Writable]]是true,則返回false. C. ?如果 desc.[[Configurable]]是true,則返回false. 3. 如果O的內部屬性[[Extensible]]為 false.,則返回true. 4. 其他情況 返回false.? ? ?15.2.3.13 Object.isExtensible(O)(檢查指定對象是否是可擴展滴.).(注4)
當以O為參數,調用isExtensible時,就按下面的步驟進行操作:? ? ?1. 如果Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 返回O的內部屬性[[Extensible]]的值.
? ? ?15.2.3.14 Object.keys(O).(獲取一個以指定對象,可枚舉屬性名作為元素值的數組對象.)
當以O為參數,調用keys時,就按下面的步驟進行操作: 1.?如果Type(O)不是Object,或O是null,則拋出一個TypeError異常. 2. 令n為O的所有可枚舉的自身獨占屬性的數量. 3. 令array 為new Array(n)的返回值. 4. 令index 為0. 5. 迭代O的每一個可枚舉屬性,P作為其屬性名. a. ?把ToString(index),屬性描述符{[[Value]]:P,[[Writable]]:true,[[Enumerable]]:true,[[Configurable]]:true},以及false作為參數,調用 arr的內部方法[[DefineOwnProperty]]. b. ?index 自增1. 6. 返回array.?動態方法:
? ? ?15.2.4.2 Object.prototype.toString()(ES3)
當,toString方法被調用,則按照下面的步驟進行操作: 1. 令 O為,以this的值作為參數.去調用ToObject(注5)方法的執行結果. 2. 令class為O的內部屬性[[Class]]的值. 3. 返回 '[Object ', class, ']'三個字符串進行連接的結果.?? ? ?15.2.4.3 Object.prototype.toLocaleString()(這個方法存基本沒神馬用處.更多是為了展望未來么?目前實現,最終還是去調用對象自身原型鏈上最前面的那個實現.ES3)
當toLocaleString被調用時,就按下面的步驟進行操作: 1. 令 O為,以this值為參數.調用ToObject的執行結果. 2. 令 toString 為以'toString'為參數,調用O的內部方法[[Get]]的執行結果. 3. 如果 isCallable(toString)是false,則拋出一個 TypeError異常. 4. 返回 以O作為this的值,無參調用 toString的內部方法[[Call]]的執行結果. 注意點1 : 此方法主要是為所有對象提供一個通用的本地化的序列化方法的接口.盡管并不是所有的對象都需要用這玩意.另外,Array,Number,和Date,都實現了自己的toLocaleString方法. 注意點2 : 此方法的第一個參數,已經被預留與,在將來的某個ES版本中定義.所以建議在實現這個方法時,把參數一的位置預留出來(好吧ES3就這樣說的,到現在依然還要預留下去.).? ? ?15.2.4.4 Object.prototype.valueOf()?(基本可以認為就是返回 this. ES3)
當 valueOf方法被調用時,就按下面的步驟進行操作: 1. 令 O為 this值為參數,調用ToObject的執行結果. 2. 如果 O是一個 new Object(host object)(參見15.2.2.1章節)的返回對象(注6),則? a. ?要么直接返回O,要么就返回那個依賴實現的,以構造器方式調用 Object時,所傳遞的那個對象.(假設new (hostObject) 返回 O,則 {}.valueOf.call(O),則返回 hostObject) 3. 返回 O.? ? ?15.2.4.5 Object.hasOwnProperty(V)(驗證,指定對象是有有一個名為V的自身獨占的屬性.ES3)
當以V作為參數調用 HasOwnProperty時,就按下面的步驟進行操作: 1. 令 P為 ToString(V)的執行結果. 2. 令 O 為 以this值為參數,調用 ToObject的執行結果. 3. 令 desc 為 以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. 4. 如果desc 是undefined,則返回 false. 5. 返回true. 注意1 : 和8.12.6章節的[[HasProperty]]不同.此方法不會去原型鏈上查找. 注意2 : 步驟1和2的順序,是為了確保優先在步驟1拋出相關異常的前提下,仍保證在此標準之前的版本所定義的那樣.在this的值是undefined,或null時,仍然繼續拋出異常.(注7) ??? ? ?15.2.4.6 Object.prototype.isPrototypeOf(V)(驗證this 是不是V的原型,this是不是在V的原型鏈上. ES3)
當以V為參數,調用isPrototypeOf方法時,就按下面的步驟進行操作: 1. 如果 V 不是對象,則返回false.(參考 Type(V) != Object && V !== null ) 2. 令O為以this值為參數調用ToObject的執行結果. 3. 重復步驟: a.?設置V的值為 V的內部屬性[[Prototype]]的值.(注,此時V = V.[[Prototype]]) b. 如果V是null, 返回false. c. 如果O和V引用相同的對象,返回true. 注意 步驟1和步驟2的順序,是為了提前在V不是對象的情況.然后在保證像之前版本定義的那樣,在this的值是undefined或null時的行為.(注8)? ? ?15.2.4.7 Object.prototype.propertyIsEnumerable(V)(驗證指定對象的指定屬性,是否是可枚舉的,ES3)
當以V為參數,調用propertyIsEnumerable方法時,就按下面的步驟進行操作: 1. 令 P 為ToString(V)的執行結果. 2. 領 O為 以this為參數,調用ToObject的執行結果. 3. 令 desc為,以P為參數,調用O的內部方法[[GetOwnProperty]]的執行結果. 4. 如果desc是undefined 則返回false. 5. 返回 desc.[[Enumerable]]的值. 注意1: 此方法,不考慮原型鏈. 注意2:??步驟1和2的順序,是為了確保優先在步驟1拋出相關異常的前提下,仍保證在此標準之前的版本所定義的那樣.在this的值是undefined,或null時,仍然繼續拋出異常(不解釋.同注7)注1:? 'franky'[0].本質就是訪問 new String('franky')的名為'0'的屬性.(另外new String對象,還有一個屬性叫length.) 所以.getOwnPropertyNames,也要枚舉出他們. 唯一要注意的是 getOwnPropertyNames,要求參數1是對象.所以你需要人肉包裝箱一下. 哦不得不提一下的是. IE8居然沒有對new String()實現索引器.而只對Primitive Strng實現了. 不得不說是坑爹行為啊.當然這和ES5無關.
注2:??也就是說,只有某屬性是一個數據屬性,才會把該屬性設置為只讀,否則還是要以訪問器 setter 為優先. 參考下面的代碼:
| var _name = 'franky', ??? obj = Object.create( ??????? Object.prototype, ??????? { ??????????? name : { ??????????????? set : function (name) { ??????????????????? _name = name; ??????????????? }, ??????????????? get : function () { ??????????????????? return _name; ??????????????? } ??????????? } ??????? } ??? ); Object.freeze(obj); obj.name = 'wait'; alert(obj.name);?//成功的打印?'wait'. |
注3:?所謂所有數據屬性都只讀.是指.不理會訪問器屬性的狀態.參考下面的代碼:
| var _name = 'franky' var obj = { ??? }; Object.defineProperty(obj, 'name', {set : function (val) {_name = val;} , get : function () {return _name;}}); Object.freeze(obj); obj.name = 'wait'; Object.isFrozen(obj);?// true |
注4:?對于[[Extensible]]為false的對象來說, v8引擎實現有一個有趣的bug.雖然這個也許不能稱之為bug.參考下面的代碼:
| var obj = {}, ??? v; Object.preventExtensions(obj);//Safari5,暫時沒有實現這個接口. v = obj.name = 123; v;// chrome: undefined. ?undefined. 這里 v8引擎嚴重有問題. 按照賦值語句的運算規則.obj.name = 123整個語句的返回值應該是 = 右邊賦值表達式的返回值 ,也就是123. 那么此處v的值應該是123. ? ? ? ? ? 此處firefox4+,ie9的實現是正確的 ? ? ? ? ? 這個問題的根源,根據v8的源碼猜測: ? ? ? ???C++ code: ? ? ? ???if (!map()->is_extensible()) { if (strict_mode == kNonStrictMode) { ????????return isolate->heap()->undefined_value(); ????? } else { ??????? Handle<Object> number = isolate->factory()->NewNumberFromUint(index); ??????? Handle<String> name = isolate->factory()->NumberToString(number); ??????? Handle<Object> args[1] = { name }; ??????? Handle<Object> error = ??????????? isolate->factory()->NewTypeError("object_not_extensible", ???????????????????????????????????????????? HandleVector(args, 1)); ??????? return isolate->Throw(*error); ?} 很明確,在非嚴格模式下,這里就是返回undefined.但為什么局部的賦值語句的返回值,沒有遵守ES的賦值語句的執行過程.而是對中間的表達式進行了求值.并當做返回值呢?這顯然是不合理的. |
注5:??邏輯運算 ToObject的作用就是,如果允許,則把目標轉換成一個object.并返回. 規則很簡單. 如果是 undefined,或null.拋出異常,如果是一個object,則不發生轉換.如果是類型是String,Number,Boolea. 則調用其對應的構造器,創建一個包裝對象. ?但實際上.Object.prototype.toString 是無法通過類似于 'abc'.toString()來調用的. 其toString方法都被重寫了. 比如String.prototype.toString. 所以我們需要這樣來調用. {}.toString.call('')或 Object.prototype.toString.call(''). 此處對于ES3來說,ToObject這一步驟在ES3中并沒有明文說明.但是瀏覽器實現的行為,也都是與ES5所描述的,是相同的.這個很好理解了.否則瀏覽器實現起來就會有問題. 至少一個 'abc' 是不存在 [[Class]]內部屬性的,因為他不是一個對象.
注6:?這里比較糾結.因為new Object(host object)的結果是依賴實現的.就是說返回啥,ES沒有定義.完全看宿主環境實現.但絕大多數實現(我所知道的,測試過的)都是,?這個host object自身. 那么我們在一般情況下,都可以理解為,如果 O 是一個宿主對象.
注7:?第二點,是指對于早期版本,比如ES3來說 1和2的步驟是反過來的.但是我個人根本沒有看出,更改順序有什么意義. 對于toString(V)的過程.拋出異常的可能性微乎其微.所以我覺得老版本的順序更加合理.而對于老版本來說,this的值是不可能為null 或 undefined.的,所以不可能有相關的異常出現.但就實現上來說.Safari似乎有些問題:
| 'use strict'; alert({}.hasOwnProperty.call(null,'a')); //無論是否在嚴格模式. Chrome,IE9,FF4+ 都拋出異常. 而Safari5一律返回false.這是不合理的. 這個問題產生的原因,大概和Safari5不支持嚴格模式有關.所以其總是保證this有一個值有關. 參考: 'use strict'; function () {return this;}();?//Safari5?中this 仍然指向 global |
注8:?這里又尼瑪沒有明確一個問題,就是當this是 null或undefined時的行為. 參考下面的代碼:
| 'use strict';??//開啟嚴格模式 alert({}.isPrototypeOf.call(undefined,undefined)); 非嚴格模式,總是會保證一個執行環境相關聯的this的值是一個對象. 比如指向global, 但是嚴格模式中,this的值就可能是null 或 undefined.那么ToObject(undefined),是一定要拋出異常的. 根據注7的部分實現. 發現Firefox在這里的處理,不符合預期. 你應該拋出異常啊伙計...Safari不拋我可以理解.你又在搞什么啊,混蛋?. |
轉載于:https://www.cnblogs.com/_franky/articles/2149843.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的ECMA262 Edition5 Object,Object的属性和方法,Object.prototype的方法.的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拒绝图片延迟加载,爽爽的看美图
- 下一篇: C# 中奇妙的函数–6. 五个序列聚合运