原文:http://pouyang.javaeye.com/blog/576127
對于丑陋的事物,愛會閉目無視
JavaScript中的對象是可變的鍵控集合(keyed collections)
對象是屬性的容器,其中每個屬性都擁有名字和值。屬性的名字可以是
包括字符串在內的任意字符串,屬性值可以是除undefined值之外的任何值
JavaScript中的對象是無類別的,它對新屬性的名字和值沒有約束。對象適合
用于收集和管理數據。對象可以包含其他對象,所以它們可以容易地表示成
樹形或圖形結構(注意:樹和圖強大的數據結構)
JavaScript包括一個原型鏈特性,允許對象繼承另一對象的屬性。正確地使用它能
減少對象初始化的時間和內存消耗
對象檢索
||運算符可以用來填充默認值
原型
返回對象類型原型的引用。
objectName.prototype
objectName 參數是對象的名稱
原型連接在更新時是不起作用的,當我們對某個對象做出改變時,不會觸及到該對象
的原型,原型連接只有在檢索值的時候才被用到,如果我們嘗試去獲取對象的某個屬性,且
該對象沒有此屬性,那么JavaScript會試著從原型對象中獲取屬性值。如果那個原型對象也
沒有該屬性,那么再從它的原型中尋找,依次類推,直到該過程最后到達
終點Object.prototype,如果想要的屬性完全不存在于原型鏈中,那么結果就是
undefied值,這個過程成為委托。
此處轉載 http://fengsky491.javaeye.com/blog/228583 謝謝 fengsky491
JScript里的prototype,為什么我們說它和prototype pattern里的prototype不一樣呢?! 這個不是我說就說出來的,也不是我吹出來的,看看這個示例,你就能大概糊涂:?
??? 好玩吧,看出來什么名堂了嗎?這里的RP.PropertyA和RP.MethodA只是用來做參照的,可是怎么把this.PropertyA和this.MethodA都delete了,還能出來結果,而且還是prototype導入的屬性和方法呢?
??? 這就是JScript的prototype和prototype pattern中prototype最大的不同了,JScript中的這個所謂的prototype屬性其實是個語言本身支持的特性,這里沒有發生任何的copy,不管shallow還是deep的。對于JScript的解釋引擎,它在處理"."或"[keyName]"引用的對象的屬性和方法時,先在對象本身的實例(this)中查找,如果找到就返回或執行。如果沒有查找到,就查找對象的prototype(this.constructor.prototype)里是否定義了被查找的對象和方法,如果找到就返回或執行,如果沒有查找到,就返回undefined(對于屬性)或runtime error(對于方法)。
??? 正因為prototype導入類實例的屬性或方法是動態查找的,所以我們才能對系統內部對象添加prototype屬性和方法,比如給String對象添加trim方法:
? 顯然JScript中的這種用法也是prototype pattern中的prototype不能解釋和支持的。
??? 這下對于JScript OOP中原型繼承法的理解因該沒有任何的障礙了吧?同時也應該明白為什么原型繼承法有那么大的天生缺陷了吧?當然如果有任何問題,歡迎繼續討論。
反射
檢查對象并確定對象有什么屬性是很容易的事情,只要試著去檢索
該屬性并驗證取得的值,typeof操作符對確定屬性的類型很有幫助。
另一個方法是使用hasOwnProperty方法,如果對象擁有獨有的屬性,它將返回true.
hasOwnProperty方法不會檢查原型連
枚舉(對象屬性)
for in 語句可用來遍歷一個對象中的所有屬性名,該枚舉過程將會列出所有的屬性
包括函數和你可能不關心的原型中的屬性,所以有必要過濾掉那些你不想要的值。最為常用
的過濾器是hasOwnProperty方法,以及使用typeof來排除函數:
屬性名出現的順序是不確定的,因此要對任何可能出現的順序有所準備,如果你想要確保屬性以特定的順序出現,
最好的辦法就是完全避免使用 for in語句,而是創建一個數組,在其中以正確的順序包含屬性名
正確的順序取得了它們的值。
對于丑陋的事物,愛會閉目無視
JavaScript中的對象是可變的鍵控集合(keyed collections)
對象是屬性的容器,其中每個屬性都擁有名字和值。屬性的名字可以是
包括字符串在內的任意字符串,屬性值可以是除undefined值之外的任何值
JavaScript中的對象是無類別的,它對新屬性的名字和值沒有約束。對象適合
用于收集和管理數據。對象可以包含其他對象,所以它們可以容易地表示成
樹形或圖形結構(注意:樹和圖強大的數據結構)
JavaScript包括一個原型鏈特性,允許對象繼承另一對象的屬性。正確地使用它能
減少對象初始化的時間和內存消耗
對象檢索
- var ?empty_object?=?{}; ??
- var ?stooge?=?{ ??
- ???? "first-name" : "Ouyang" , ??
- ???? "last-name" : "ping" , ??
- ???? "yyl" : "yyl" ??
- } ??
- alert(stooge[ "first-name" ]);? //Ouyang ??
- alert(stooge.first-name); //NaN ??
- alert(stooge.yyl) //yyl ??
- alert(stooge.name); //undefined ??
var empty_object = {}; var stooge = { "first-name":"Ouyang", "last-name":"ping", "yyl":"yyl" } alert(stooge["first-name"]); //Ouyang alert(stooge.first-name);//NaN alert(stooge.yyl)//yyl alert(stooge.name);//undefined
||運算符可以用來填充默認值
- var?middle?=?stooge["middle-name"]?||"none"; ??
- ??
- flight.equipment?//?undefined ??
- flight.equipment.model?//?throw?"TypeError" ??
- flight.equipment?&&?flight.equipment.model?//undefined??
var middle = stooge["middle-name"] ||"none"; flight.equipment // undefined flight.equipment.model // throw "TypeError" flight.equipment && flight.equipment.model //undefined
原型
返回對象類型原型的引用。
objectName.prototype
objectName 參數是對象的名稱
原型連接在更新時是不起作用的,當我們對某個對象做出改變時,不會觸及到該對象
的原型,原型連接只有在檢索值的時候才被用到,如果我們嘗試去獲取對象的某個屬性,且
該對象沒有此屬性,那么JavaScript會試著從原型對象中獲取屬性值。如果那個原型對象也
沒有該屬性,那么再從它的原型中尋找,依次類推,直到該過程最后到達
終點Object.prototype,如果想要的屬性完全不存在于原型鏈中,那么結果就是
undefied值,這個過程成為委托。
- function?TestObjectA()? ??
- {? ??
- ????this.MethodA?=?function()? ??
- ????{? ??
- ???????alert('TestObjectA.MethodA()');? ??
- ????}? ??
- }? ??
- ??
- function?TestObjectB()? ??
- {? ??
- ????this.bb?=?'ccc'; ??
- ????this.MethodB?=?function()? ??
- ????{? ??
- ???????alert('TestObjectB.MethodB()');? ??
- ????}? ??
- }? ??
- ??
- TestObjectB.prototype?=?new?TestObjectA();?//TestObjectB繼承了?TestObjectA的方法 ??
- ??
- TestObjectB.prototype.bb?=?'aaaaa';?//添加屬性 ??
- var?temp ??
- var?b?=?new?TestObjectB(); ??
- for?(temp?in?b)?{ ??
- ??alert(temp);?//?MethodA??bb?MehtedB ??
- } ??
- var?kk?=?new?TestObjectB(); ??
- //刪除,但原型鏈中的沒有刪除 ??
- alert(kk.bb);?//?ccc ??
- delete?kk.bb; ??
- alert(kk.bb);?//?aaaa ??
- ??
- alert(kk.MethodA());?//TestObjectA.MethodA()??
function TestObjectA() { this.MethodA = function() { alert('TestObjectA.MethodA()'); } } function TestObjectB() { this.bb = 'ccc'; this.MethodB = function() { alert('TestObjectB.MethodB()'); } } TestObjectB.prototype = new TestObjectA(); //TestObjectB繼承了 TestObjectA的方法 TestObjectB.prototype.bb = 'aaaaa'; //添加屬性 var temp var b = new TestObjectB(); for (temp in b) { alert(temp); // MethodA bb MehtedB } var kk = new TestObjectB(); //刪除,但原型鏈中的沒有刪除 alert(kk.bb); // ccc delete kk.bb; alert(kk.bb); // aaaa alert(kk.MethodA()); //TestObjectA.MethodA()
此處轉載 http://fengsky491.javaeye.com/blog/228583 謝謝 fengsky491
JScript里的prototype,為什么我們說它和prototype pattern里的prototype不一樣呢?! 這個不是我說就說出來的,也不是我吹出來的,看看這個示例,你就能大概糊涂:?
- ?<script?language="javascript"> ??
- function?RP()? ??
- {? ??
- ????RP.PropertyA?=?1;? ??
- ????RP.MethodA?=?function()? ??
- ????{? ??
- ?????????alert("RP.MethodA?");? ??
- ????};? ??
- ???? ??
- ????this.PropertyA?=?100;? ??
- ????this.MethodA?=?function()? ??
- ????{? ??
- ?????????alert("this.MethodA");? ??
- ????};? ??
- }? ??
- ??
- RP.prototype.PropertyA?=?10;? ??
- RP.prototype.MethodA?=?function()? ??
- {? ??
- ????alert("RP.prototype.MethodA");? ??
- };? ??
- </script>???
<script language="javascript"> function RP() { RP.PropertyA = 1; RP.MethodA = function() { alert("RP.MethodA "); }; this.PropertyA = 100; this.MethodA = function() { alert("this.MethodA"); }; } RP.prototype.PropertyA = 10; RP.prototype.MethodA = function() { alert("RP.prototype.MethodA"); }; </script>?? 不要著急,還沒有開始做示例,只是給出了我們用來演示的一個類。RP是什么?rpwt嗎?當然不是了,RP是ResearchPrototype了。好了不廢話了,看示例及結果分析。??
- <script?language="javascript">? ??
- rp?=?new?RP();? ??
- alert(RP.PropertyA);? ??
- RP.MethodA();? ??
- alert(rp.PropertyA);? ??
- rp.MethodA();? ??
- </script>? ??
- ????運行結果閃亮登場:? ??
- ???1? ??
- ???RP.MethodA? ??
- ???100? ??
- ???this.MethodA? ??
- ????這個%$@#^$%&^...,不要著急,繼續看哦!???
<script language="javascript"> rp = new RP(); alert(RP.PropertyA); RP.MethodA(); alert(rp.PropertyA); rp.MethodA(); </script> 運行結果閃亮登場: 1 RP.MethodA 100 this.MethodA 這個%$@#^$%&^...,不要著急,繼續看哦!
- <script?language="javascript">? ??
- rp?=?new?RP();? ??
- delete?RP.PropertyA;? ??
- alert(RP.PropertyA);? ??
- delete?RP.MethodA;? ??
- RP.MethodA();? ??
- delete?rp.PropertyA;? ??
- alert(rp.PropertyA);? ??
- delete?rp.MethodA;? ??
- rp.MethodA();? ??
- </script>? ??
- ????運行結果再次登場:? ??
- ???undefined? ??
- ???A?Runtime?Error?has?occurred.? ??
- ???Do?you?wish?to?Debug?? ??
- ???Line:?32? ??
- ???Error:?Object?doesn't?support?this?property?or?method? ??
- ???10? ??
- ???RP.prototype.MethodA???
<script language="javascript"> rp = new RP(); delete RP.PropertyA; alert(RP.PropertyA); delete RP.MethodA; RP.MethodA(); delete rp.PropertyA; alert(rp.PropertyA); delete rp.MethodA; rp.MethodA(); </script> 運行結果再次登場: undefined A Runtime Error has occurred. Do you wish to Debug? Line: 32 Error: Object doesn't support this property or method 10 RP.prototype.MethodA
??? 好玩吧,看出來什么名堂了嗎?這里的RP.PropertyA和RP.MethodA只是用來做參照的,可是怎么把this.PropertyA和this.MethodA都delete了,還能出來結果,而且還是prototype導入的屬性和方法呢?
??? 這就是JScript的prototype和prototype pattern中prototype最大的不同了,JScript中的這個所謂的prototype屬性其實是個語言本身支持的特性,這里沒有發生任何的copy,不管shallow還是deep的。對于JScript的解釋引擎,它在處理"."或"[keyName]"引用的對象的屬性和方法時,先在對象本身的實例(this)中查找,如果找到就返回或執行。如果沒有查找到,就查找對象的prototype(this.constructor.prototype)里是否定義了被查找的對象和方法,如果找到就返回或執行,如果沒有查找到,就返回undefined(對于屬性)或runtime error(對于方法)。
??? 正因為prototype導入類實例的屬性或方法是動態查找的,所以我們才能對系統內部對象添加prototype屬性和方法,比如給String對象添加trim方法:
- <script?lanuage="javascript">? ??
- String.prototype.trim()? ??
- {? ??
- ????return?this.replace(/(^\s+)|(\s+$)/g,?"");? ??
- }? ??
- </scritp>???
<script lanuage="javascript"> String.prototype.trim() { return this.replace(/(^\s+)|(\s+$)/g, ""); } </scritp>?
? 顯然JScript中的這種用法也是prototype pattern中的prototype不能解釋和支持的。
??? 這下對于JScript OOP中原型繼承法的理解因該沒有任何的障礙了吧?同時也應該明白為什么原型繼承法有那么大的天生缺陷了吧?當然如果有任何問題,歡迎繼續討論。
反射
檢查對象并確定對象有什么屬性是很容易的事情,只要試著去檢索
該屬性并驗證取得的值,typeof操作符對確定屬性的類型很有幫助。
- typeof?flight.number??
typeof flight.number
另一個方法是使用hasOwnProperty方法,如果對象擁有獨有的屬性,它將返回true.
hasOwnProperty方法不會檢查原型連
- flight.hasOwnProperty('nubmer');??
flight.hasOwnProperty('nubmer');
枚舉(對象屬性)
for in 語句可用來遍歷一個對象中的所有屬性名,該枚舉過程將會列出所有的屬性
包括函數和你可能不關心的原型中的屬性,所以有必要過濾掉那些你不想要的值。最為常用
的過濾器是hasOwnProperty方法,以及使用typeof來排除函數:
- var?name; ??
- for?(name?in?another_stooge)?{ ??
- ????if?(typeof?another_stooge[name]?!=?'function')?{ ??
- ????????document.writeln(name+':'+another_stooge[name]); ??
- ????} ??
- }??
var name; for (name in another_stooge) { if (typeof another_stooge[name] != 'function') { document.writeln(name+':'+another_stooge[name]); } }
屬性名出現的順序是不確定的,因此要對任何可能出現的順序有所準備,如果你想要確保屬性以特定的順序出現,
最好的辦法就是完全避免使用 for in語句,而是創建一個數組,在其中以正確的順序包含屬性名
- var?i?; ??
- var?properties?=?[ ??
- ????'first-name', ??
- ????'middle-name', ??
- ????'last-name', ??
- ????'profession'??
- ]; ??
- for?(i?=?0?;?i?<?properties.length;?i?+=?1)?{ ??
- ????document.writeln(properties[i]+':'+another_stooge[properties[i]]); ??
- }??
var i ; var properties = [ 'first-name', 'middle-name', 'last-name', 'profession' ]; for (i = 0 ; i < properties.length; i += 1) { document.writeln(properties[i]+':'+another_stooge[properties[i]]); }通過使用for而不是for in ,可以得到我們想要的屬性,而不用擔心可能發掘出原型鏈中的屬性,并且我們按
正確的順序取得了它們的值。