首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

怎么判断一个函数的意图是被用作构造器,也就是可视为“类”

2012-09-12 
如何判断一个函数的意图是被用作构造器,也就是可视为“类”前提是不要求做什么特殊标记。只是最大可能的猜测

如何判断一个函数的意图是被用作构造器,也就是可视为“类”
前提是不要求做什么特殊标记。只是最大可能的猜测函数的作用大概是当“类”使用。


我想了一个方式:

function isClass(f) {
  var names = Object.keys(f.prototype)
  return names.indexOf('constructor') === -1 || names.length > 1
}

这里的假设是,作为构造器的函数会在其prototype上加公共方法。

prototype上默认是有 constructor 属性(指向函数自身)。那么如果keys(prototype上的属性名列表)的长度大于1,意味着作者执行过 f.prototype.xxx = ... ,或者keys不包含constructor属性,意味着作者很可能执行过 f.prototype = { xxx:... } 。这样我们就认为这个函数的意图是被当作构造器(类)来用。

各位如何看?

有什么别的idea么?


【7月24日更新】

之前的方法有一些小问题,根据标准,constructor属性应是不可enumerable的。所以Object.keys并不会包含constructor属性(感谢jk和luolonghao指出问题)。上面的代码可直接改为:

function isClass(f) {
  var names = Object.keys(f.prototype)
  return names.length > 0
}

但考虑旧引擎,则其相关ES5方法是由如es5-shim之类的库补上,行为不是最标准,比如无法知道一个属性是否是enumerable的(这就是jk怀疑的什么引擎会返回constructor,呵呵)。

另外,若f.prototype上存在不可枚举属性,说明什么呢?难道就是不想作为类吗?一个case是我可能希望方法不可枚举。所以可修改如下:

function isClass(f) {
  var names = Object.getOwnPropertyNames(f.prototype)
  return names.length > 1 || names[0] !== 'constructor'
}

这里还存在一个问题。prototype可以是原型继承得来的,上面own properties没有,但是有许多其他继承来的property,那么我们可能需要上溯所有原型(感谢limu提出这个问题)。


不过我直觉上溯并不是好办法,所以我重新考虑我的基本出发点:

原始function(){}的prototype值是一个new Object()结果,且其上定义了constructor属性指向该函数自身。

基本想法是:我们判断当前函数的情况是否和上面一致,如果不一致,则其目的很可能是为了将该函数作为一个类构造器来使用。

所以,最后得到这个版本:

function Person(name){this.name = name;}alert(likeConstructor(Person));//chrome falsevar p1 = new Person("a");

这是个小问题,如果没有prototype上的动作应该直接var p2 = {name:"a"}.
但也不能说这个写法完全没有意义.一方面,可能后续会添加OwnProperty,
另一方面,console.log(p1)控制台会明确告诉p1是一个Person,而log(p2)则肯定是Object.

之所以测试了这个,你在最初提出这个问题的时候,我在想constructor的一个特点,构造函数体内常常有this引用.而普通function一般不会.


你说的这个情况,一开始就考虑过。如果不修改prototype,全部在构造器里通过this引用添加属性,确实也是可行的,检测不出来。但这样的构造器本质上就无法准确检测出来,因为它和一般的method无法区分(method里有都有this引用),除非你认为函数名大写可以表明它是“构造器”,这又回到了命名约定的路子上去了。

或许还是应该把名字改回为likeClass()?这样可认为不带有prototype的不like Class? 7 楼 yiminghe 2011-07-25   bind 的为啥不能作为构造器(不推荐?),mdc上有个构造器的例子 8 楼 yiminghe 2011-07-25   bind 构造器还是挺好玩的,this 不起作用,但是参数还是可以的 9 楼 hax 2011-07-25   yiminghe 写道bind 构造器还是挺好玩的,this 不起作用,但是参数还是可以的

没有this还哪里有新对象呀!这咋做构造器呢? 10 楼 yiminghe 2011-07-25   hax 写道yiminghe 写道bind 构造器还是挺好玩的,this 不起作用,但是参数还是可以的

没有this还哪里有新对象呀!这咋做构造器呢?

指 bind 的参数 thisArg没用 11 楼 enix2212 2011-07-27   instaceof  不能么?

热点排行