JS屬性操作的基礎知識
Js對象的屬性是可以動態擴展的譬如:定義了一個js對象,就可以設置它的屬性。代碼如下:
Object.prototype.test = “test1”;//定義一個Object的擴展屬性,以後所有的Object都有該屬性
Object.test1 = “abc”;//定義一個Ojbect的靜態屬性
var obj = {};//定義一個Object對象,也可以寫爲:var obj = new Object();
obj.prop1 = “prop1”;//設置obj的prop1屬性,若該屬性存在則爲其重新設置值,若不存在則添加該屬性.
obj.prop2 = “prop2”;//設置obj的prop2屬性.
obj[“prop3”] = “prop3”;//同上,設置prop3屬性.
var prop4 = “prop4”;
obj[prop4] = “testProp4”;//設置obj的prop4屬性,很多人問如何把一個變量設置爲一個對象的屬性.
alert(obj.prop1);//彈出”prop1”
alert(obj[“prop2”]);//彈出”prop2”
alert(obj[“test”]);//彈出”test1”
alert(obj.test1);//彈出undefined
alert(Object.test1);//彈出”abc”;
var obj1 = {};
alert(obj1.prop1);//彈出undefined
alert(obj1.test);//彈出”test1”
可能出現的問題
我們原定用對象的方式存entity.如下:
var obj = new Object()
obj[“name”] = “name1”;
obj[“sex”] = “男”;
這種方法存儲的是擴展屬性,因此必須用下面方法遍歷:
for(var key in arr){
key…//name,sex…
arr[key]…name1,男…
}
但是如果我們給Object加了擴展屬性.如
Object.prototype.remove = function(index){
…
}
那麼遍歷出來的值就多了一個
for(var key in arr){
key…//remove,name,sex…
arr[key]…remove的函數實體,name1,男…
}
這是無法避免的.
而如果我們給Object加上擴展屬性則,所有的對象都會有這個屬性.所有對象遍歷出來的結果與實際不符合.
這個問題可能會在以後暴露.如果我們以後引入了其它JS框架,它們很多都是擴展js的對象屬性.那麼將會發生莫名其妙的錯誤.
這裏給出一個流行的javascript的HashMap的實現
<script language="javascript">
function HashMap()
{
/** Map 大小 **/
var size = 0;
/** 對象 **/
var entry = new Object();
/** 存 **/
this.put = function (key , value)
{
if(!this.containsKey(key))
{
size ++ ;
}
entry[key] = value;
}
/** 取 **/
this.get = function (key)
{
return this.containsKey(key) ? entry[key] : null;
}
/** 刪除 **/
this.remove = function ( key )
{
if( this.containsKey(key) && ( delete entry[key] ) )
{
size --;
}
}
/** 是否包含 Key **/
this.containsKey = function ( key )
{
return (key in entry);
}
/** 是否包含 Value **/
this.containsValue = function ( value )
{
for(var prop in entry)
{
if(entry[prop] == value)
{
return true;
}
}
return false;
}
/** 所有 Value **/
this.values = function ()
{
var values = new Array();
for(var prop in entry)
{
values.push(entry[prop]);
}
return values;
}
/** 所有 Key **/
this.keys = function ()
{
var keys = new Array();
for(var prop in entry)
{
keys.push(prop);
}
return keys;
}
/** Map Size **/
this.size = function ()
{
return size;
}
/* 清空 */
this.clear = function ()
{
size = 0;
entry = new Object();
}
}
var map = new HashMap();
/*
map.put("A","1");
map.put("B","2");
map.put("A","5");
map.put("C","3");
map.put("A","4");
*/
/*
alert(map.containsKey("XX"));
alert(map.size());
alert(map.get("A"));
alert(map.get("XX"));
map.remove("A");
alert(map.size());
alert(map.get("A"));
*/
/** 同時也可以把對象作爲 Key **/
/*
var arrayKey = new Array("1","2","3","4");
var arrayValue = new Array("A","B","C","D");
map.put(arrayKey,arrayValue);
var value = map.get(arrayKey);
for(var i = 0 ; i < value.length ; i++)
{
//alert(value[i]);
}
*/
/** 把對象做爲Key時 ,自動調用了該對象的 toString() 方法 其實最終還是以String對象爲Key**/
/** 如果是自定義對象 那自己得重寫 toString() 方法 否則 . 就是下面的結果 **/
function MyObject(name)
{
this.name = name;
}
/**
function MyObject(name)
{
this.name = name;
this.toString = function ()
{
return this.name;
}
}
**/
var object1 = new MyObject("小張");
var object2 = new MyObject("小名");
map.put(object1,"小張");
map.put(object2,"小名");
alert(map.get(object1));
alert(map.get(object2));
map.remove("xxxxx");
alert(map.size());
/** 運行結果 小名 小名 size = 1 **/
/** 如果改成複寫toString()方法的對象 , 效果就完全不一樣了 **/
</script>
這種方法的原理就是用property,用Object的擴展屬性.來存儲內容
這會有一個問題.
如果我們使用了prototype.js它上面定義了一個Object的繼承方法:
Object.prototype.extend = function(obj){
……
}
那麼,下面代碼會出現問題.
this.keys = function ()
{
var keys = new Array();
for(var prop in entry)//遍歷所有entry的屬性 var entry = new Object();prop是Ojbect的擴展屬性.
{
keys.push(prop);
}
return keys;
}
我們獲得的keys裏會包含”extend”這一項.這和我們要的不一致,這在一般的應用很難出問題,然而如果遇到這種情況,可能就找不到原因了。如果我們開發的時候寫了這樣的代碼:map.put(“extend”,”test”);或者map.remove(“extend”);就會覆蓋prototype 定義的Object.prototype.extend方法,那麼以prototype.js爲基礎的所有東西將都不能使用。
js的很多開源框架都對Object作了擴展.擴展的函數名是不可預知的.所以要避免這種情況.因爲如果出現錯誤,可能很難找出原因。