在Javascript中实现isInstance

时间:2009-10-03 16:05:59

标签: javascript inheritance instanceof

我定义了两个函数如何相互继承,如下所示:

Function.prototype.inherit = function(parent){

function proto() {}
proto.prototype = parent.prototype;

this.prototype = new proto();
this.prototype.constructor = this;
this.prototype.parent = parent; 

}

然后我需要定义一个isInstance函数,它的行为类似于Java的instanceOf或PHP的instanceof。实质上,isInstance可用于确定变量是否是从父函数继承的函数的实例化对象。

这就是我写的:

Function.prototype.isInstance = function(func){
if(this == func){
    return true;
} else{
    if (this.prototype.parent == undefined || this.prototype.parent == null) {
        return false;   
    } else {
        return this.prototype.parent.isInstance(func);          
    }
}

}

在比较两个函数时可以正常工作,但在比较实例化变量时则不行。

Object2.inherit(Object1);

Object2.isInstance(Object1); //returns true

var obj2 = new Object2();

obj2.isInstance(Object1);// obj2.isInstance is not a function

上面的最后一个案例是我想要的工作。如何将isInstance添加到实例,而不仅仅是函数?对于那里的所有javascript专家,我的代码是否有任何改进(可能是继承方法)?

感谢。

3 个答案:

答案 0 :(得分:6)

  

然后我需要定义一个isInstance函数,它的行为类似于Java的instanceOf或PHP的instanceof。

JavaScript自己的instanceof有什么问题?

鉴于你的继承功能,

function Shape() {};
function Square() {};
Square.inherit(Shape);
alert(new Square() instanceof Shape); // true

instanceof通过检查给定构造函数的prototype属性是否在实例的原型链中来工作。所以例如。

function A() {};
function B() {};
var b= new B();
A.prototype= B.prototype;
alert(b instanceof A); // true

即使instanceof Shape未使用Square.prototype创建new Shape,这也是new proto()有效的原因。相反,它是由proto创建的,但由于Shapeprototype共享相同的__proto__属性,因此JavaScript无法区分。

您通常无法看到原型链(虽然Firefox和WebKit通过new属性使其可用),但它是实际在JS中处理继承的方式;可见的Function.prototype属性仅用于在Object.prototype.isInstance(c)= function() { return this instanceof c; } - 时间设置原型链的初始状态。

  

如何将isInstance添加到实例中,而不仅仅是函数?

instanceof

我不确定这真的会让你受益匪浅!对Object进行原型设计通常被认为是不好的,因为它会影响每个对象,并且可能会使用Object将其他脚本混淆为查找映射。

  

我的代码是否有任何改进(可能是继承方法)?

我喜欢你的继承方法,它是制作对象系统的一种更轻量级的JavaScripty方法。

使用parent,您可能会丢失constructorparent属性,除非您出于其他方便目的而想要它们。我将constructor放在构造函数上(所以它就像知道它的基类的子类),我会调用constructor其他东西(已经有一个名为function Square() { Shape.apply(this, arguments); } Square.inherit(Shape); 的属性在Firefox中但它没有按照您的想法进行,通常最好避免使用。)

我看到的唯一缺点是你不能继承构造函数,所以每次你创建一个新的子类时,你必须编写一个调用基本构造函数的构造函数,即使你的子类的构造函数什么都不做:

{{1}}

答案 1 :(得分:4)

你为什么需要这样做?由于某种原因,JavaScript没有严格的类层次结构的概念:它确实无法完成。你可以找到一个大部分时间都可以工作的解决方案,但我不确定你是否可以覆盖所有边缘情况。此外,由于JavaScript没有任何接口概念,因此对显式继承的测试会导致高耦合,并且似乎违反了SOLID principles

使用duck typing是一种更好(更惯用)的方法来解决这个问题。只需测试您需要的方法的存在,然后调用它。只要准备好在必要时捕获异常(无论如何你都应该这样做)。

答案 2 :(得分:1)

要将好的设计论点搁置一秒钟并专注于您的问题,问题是您将isInstance()设置为Function原型的方法。这意味着Function的对象将拥有它,而不是的对象(例如示例中的Object1Object2)则不会。

我建议不要试图将它作为一种方法来实现,而是让它成为一个静态函数:

function isInstance(object, ofClass) {
  // Same logic as you have, except use 
  // object.prototype instead of this.prototype
}

然后您可以将其作为

调用
isInstance(obj2, Object2);