既然對象是屬性的集合,那么檢測與枚舉集合中的屬性就是一項重要任務。對此,我們來分別看一下ES3和ES5提供的解決方案。
1)?????ES3枚舉方案
示例代碼:
var contacts={
??? ID:[0,1,2,3,4,5],
??? names:["Zero","One","Two","Three","Four","Five"],
??? addresses:[
??? {
??????? Street:"ABC",
??????? State: "0"
??? },
??? {
??????? Street:"ABC",
??????? State: "1"
??? },
??? {
??????? Street:"ABC",
??????? State: "2"
??? },
??? {
??????? Street:"ABC",
??????? State: "3"
??? },
??? {
??????? Street:"ABC",
??????? State: "4"
??? },
??? {
??????? Street:"ABC",
??????? State: "5"
??? }
??? ]
};
//ES3 solutions
console.log('"ID" in contacts: ',"ID" in contacts);
console.log("'toString' in contacts: ",'toString' in contacts );
for(var key in contacts){
??? console.log("key: ",key);
??? console.log("value: ",contacts[key]);
}
上面代碼的輸出結果如下:
"ID" in contacts:? true
'toString' in contacts:? true
key:? ID
value:? [ 0, 1, 2, 3, 4, 5 ]
key:? names
value:? [ 'Zero', 'One', 'Two', 'Three', 'Four', 'Five' ]
key:? addresses
value:? [ { Street: 'ABC', State: '0' },
? { Street: 'ABC', State: '1' },
? { Street: 'ABC', State: '2' },
? { Street: 'ABC', State: '3' },
? { Street: 'ABC', State: '4' },
? { Street: 'ABC', State: '5' } ]
注意:
-
運算符in的左側是屬性名,是字符串類型,右側是對象。無論是對象的自有屬性還是繼承屬性中包含這個屬性都會返回true。
-
對象的hasOwnProperty()方法用于檢測給定的名字是否是對象的自有屬性。對于繼承屬性則返回false。例如:
var? o={a:111,b:222};
o.hasOwnProperty("a");//true
o.hasOwnProperty("x");//false:不存在此屬性
o.hasOwnProperty("toString");//false:toString是繼承屬性
-
propertyIsEnumerable()是hasOwnProperty()方法的增強版本,用于檢測自有且可枚舉的屬性。通常JS創建的屬性都是可枚舉的,除非使用ES5中特殊方法改變了屬性的可枚舉性。例如:
var? o=inherit({a:111,b:222});
o.x=10000;
o. propertyIsEnumerable ("x");//true
o. propertyIsEnumerable ("a");//false:繼承來的屬性
Object.prototype. propertyIsEnumerable ("toString");//false:toString是不可枚舉的屬性
?
2)?????ES5枚舉方案
除了使用ES3中的for...in循環方式來枚舉對象中的屬性外,對于前面定義的對象直接量,ES5還支持如下的枚舉方案:
console.log(Object.keys(contacts));
console.log(Object.getOwnPropertyNames(contacts));
輸出結果如下:
[ 'ID', 'names', 'addresses' ]
[ 'ID', 'names', 'addresses' ]
其中,靜態方法Object.keys()返回一個數組,這個數組由對象中可枚舉的自有屬性的名稱組成。
靜態方法Object. getOwnPropertyNames ()也是返回一個數組,這個數組由對象中所有的自有屬性的名稱組成。注意:ES3中無法實現這樣的方法,因為ES3中無法獲取對象的不可枚舉的屬性。
3)?????!==和in運算符用于屬性存在判斷
前面介紹使用in運算符判斷指定屬性在否存在于某對象中。其實,有些簡單情況下,也可以使用!==運算符來決斷一個屬性是否是undefined。
var oo1=new Object({lan:"JavaScript",degree:"Difficult"});
console.log("使用!==運算符的例子");
console.log(oo1.lan!==undefined);? //true
console.log(oo1.language!==undefined); //false
console.log(oo1.toString!==undefined); //true
切記:只有in運算符能夠區分不存在的屬性和存在但值為undefined的屬性。此時,!==已經無能為力。參考如下代碼片斷:
var ou={key1:undefined};
console.log("只能使用in運算符的例子");
console.log(ou.key1!==undefined);//false
console.log(ou.key2!==undefined);//false
console.log("key1" in ou);//true
console.log("key2" in ou);//false
delete ou.key1; //delete property 'key1'
console.log("key1" in ou);//false
4)?????與屬性枚舉相關的幾個工具函數
?
在本節給出的工具函數中,我們把對象看作屬性集合,所給的圖示試圖從集合論角度給出這些函數的功能示意。
求并集1
示意圖:
此工具函數并兩個對象中屬性的并集,但對于相同的屬性,使用present對象的屬性覆蓋對象orig中同名屬性。
function extend(orig,present){
??? for(var prop in present){
??????? orig[prop]=present[prop];
??? }
??? return orig;
}
?
求并集2
示意圖:
此工具函數并兩個對象中屬性的并集,但對于相同的屬性,使用保留對象orig中的屬性而舍棄present中同名屬性。
function merge(orig,present){
??? for(var prop in present){
??????? if(orig.hasOwnProperty(prop)) continue;
??????? orig[prop]=present[prop];
??? }
??? return orig;
}
求交集1
此工具函數并兩個對象中屬性的交集,但對于相同的屬性,使用保留對象orig中的屬性而舍棄present中同名屬性。
function restrict(orig,present) {
??? for(var prop in orig){
??????? if(!(prop in present)){
??????????? delete orig[prop];
??????? }
??????? return orig;
??? }
}
求交集2
此工具函數并兩個對象中屬性的交集,但對于相同的屬性,使用保留對象orig中的屬性而舍棄present中同名屬性。因此,交集結果同上面“求交集1”,但是返回新集合。
function intersection(o,p) {
??? return restrict(extend({},o),p);
}
求集合減法
function subtract(orig,present) {
??? for (var prop in present) {
??????? delete? orig[prop];
??? }
??? return orig;
}
?
求并集3
實際上等同于“求并集1”,但是返回一個新對象。
function union(orig,present) {
??? return extend(extend({},orig),present);
}
類似于ES5版本的Object.keys(o)
function keys(obj){
??? if(typeof obj!=="object") throw TypeError("The parameter 'obj' must be an object!");
??? var result=[];
??? for(var prop in obj){
??????? if(obj.hasOwnProperty(prop)){
??????????? result.push(prop);
??????? }
??? }
??? return result;
}
求多個集合并集的函數
下面這個工具函數在許多JS庫中都有它的影子,來自于
Pomelo示例工程中的文件
chatofpomelo-websocket\game-server\node_modules\pomelo\node_modules\cliff\node_modules\winston\lib\winston\config.js,可以實現多個集合并集求解。
但對于相同屬性,使用后面加入的集合中同名屬性覆蓋前面集合中屬性。
function mixin (targetObj) {
??? //下面代碼把函數的參數轉換成一個數組,并取得從第1個元素開始直到最后的參數組成的子數組
??? var args = Array.prototype.slice.call(arguments, 1);
??? args.forEach(function (a) {
??????? var keys = Object.keys(a);//ES5:?返回對象所有自有屬性的名稱
??????? for (var i = 0; i < keys.length; i++) {
??????????? targetObj[keys[i]] = a[keys[i]];
??????? }
??? });
??? return targetObj;
};
?
以上屬性操作工具函數還存在不同程度的缺點,僅供學習者參考。
本文轉自朱先忠老師51CTO博客,原文鏈接:http://blog.51cto.com/zhuxianzhong/1653360?,如需轉載請自行聯系原作者