在一些时候下,我们需要能够在对对象完全不了解的情况下进行处理,并且在处理之前发现他们的属性和方法,这个过程称作反射(reflection)。Java和.Net对这个有很好的支持和拓展,那么在Javascript中怎么来实现发射?以下进行详细的解析。
为了检测一个Javascript对象是否支持一个特定的属性或者方法,或者为了检测用户当前使用的浏览器(针对某些浏览器不兼容的Javascript对象或者属性与方法)时,一般可以简单地这么做:
if(someObj.someProperty){
//...
}
然而,如果someObj.someProperty被赋值为:布尔值false、数字0或者特殊值null时,这种方法就会失败或者说有漏洞。更好的方法是:
if(typeof(someObj.someProperty) != 'undefined'){
//...
}
如果我们关心对象或者其属性的类型,可以使用instanceof操作符,如下:
if(someObj instanceof Array){
//...
}
else if(someObj instanceof Object){
//...
}
可以检测出ECMAScript的内建基本类型。也可以识别出任何通过构造函数来定义的类:
function MyObject(id, name){
this.Id = id;
this.Name = name;
}
var someObj = new MyObject('007', 'Langzi127');
if(someObj instanceof MyObject){
//...
}
然而,这个方法也有2个缺陷:
1. 使用JSON创建的类不支持它,因为使用JSON创建的类要么是一个Object,或者是一个Array;
2. 内建的对象支持存在与它们中间的继承。如:Function和Array都继承自Object,所以测试顺序是相关的。如:
if(someObj instanceof Array || someObj instanceof Function){ //条件1
//...
}
else if(someObj instanceof Object){ //条件2
//...
}
能够得到我们想要的结果,但是如果更换条件1和条件2的位置,则未必。
有时我们希望无遗漏的发现一个对象的所有属性和函数,可以使用for循环:
function MyObject(id, name){
this.Id = id;
this.Name = name;
}
var someObj = new MyObject('007', 'Langzi127');
for(var i in someObj){
alert(someObj[i]);
}
一个典型的应用是在Ajax中动态修改DOM元素的CSS样式。如下:
var element = getElementById('elementID');
//第一次设置element的样式
element.style.color = 'red'; //设置1
element.style.display = 'block'; //设置2
var newStyle = {
color:#ffffff,
backgroundColor:#ff0000,
borderWidth:2px
}
function setStyle(_style){
for(var p in _style){
element.style[p]=_style[p];
}
}
//第二次(修改)设置element的样式
setStyle(newStyle);
这种好处就是不会覆盖第一次设置的(设置2),同时会修改(设置1)。这是与newStyle的具体样式设置相关。