JavaScript服务器端开发技术(对象属性的枚举与查询)
既然对象是属性的集合,那么检测与枚举集合中的属性就是一项重要任务。对此,我们来分别看一下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 solutionsconsole.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: truekey: IDvalue: [ 0, 1, 2, 3, 4, 5 ]key: namesvalue: [ 'Zero', 'One', 'Two', 'Three', 'Four', 'Five' ]key: addressesvalue: [ { 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");//trueo.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");//trueo. 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); //trueconsole.log(oo1.language!==undefined); //falseconsole.log(oo1.toString!==undefined); //true切记:只有in运算符能够区分不存在的属性和存在但值为undefined的属性。此时,!==已经无能为力。参考如下代码片断:var ou={key1:undefined};console.log("只能使用in运算符的例子");console.log(ou.key1!==undefined);//falseconsole.log(ou.key2!==undefined);//falseconsole.log("key1" in ou);//trueconsole.log("key2" in ou);//falsedelete 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;};
以上属性操作工具函数还存在不同程度的缺点,仅供学习者参考。
阅读更多- JavaScript服务器端开发技术(对象属性的枚举与查询)
- 从零开始学_JavaScript_系列(40)——对象的扩展(3)当枚举、原型链遇见对属性的操作
- 插件开发技术(9)---SQL查询记录与对象的映射
- JavaScript服务器端开发(函数实参对象arguments使用的几个注意事项)
- javascript 对象原型,原型链,属性枚举
- JavaScript对象、属性、事件手册查询 (整)
- JavaScript对象、属性、事件手册集合方便查询
- 【JavaScript】中枚举对象中的属性
- JavaScript对象中的属性(可写,可配置,可枚举,value,getter,setter)
- javascript基础(对象,对象属性,属性基本和引用数据类型,字面量创建对象,垃圾回收,属性的枚举)(十三)
- JavaScript对象.属性]集锦、事件查询综合
- Web开发技术 ——JavaScript语法2(变量、数据类型、对象)
- 转载:JavaScript对象、属性、事件手册查询
- javascript封装判断全数据类型方法, toString方法, 对象的枚举(in, instanceof, hasOwnProperty的用法), arguments类数组属性
- JavaScript服务器编程(对象属性枚举中应当避免原型污染问题)
- JavaScript[对象.属性]集锦、事件查询综合
- JavaScript服务器编程(对象属性枚举中应当避免原型污染问题)
- JavaScript[对象.属性]集锦、事件查询综合
- JavaScript学习笔记:对象属性的枚举
- JavaScript之枚举属性的对象函数