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