0

I define how two functions can inherit from each other as follows:

Function.prototype.inherit = function(parent){

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

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

}

I then need to define an isInstance function that would behave like Java's instanceOf or PHP's instanceof. In essence, isInstance could be used to determine whether a variable is an instantiated object of a function that inherits from a parent function.

This is what I wrote:

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);          
    }
}

}

Which works fine when comparing two functions, but not when comparing instantiated variables.

Object2.inherit(Object1);

Object2.isInstance(Object1); //returns true

var obj2 = new Object2();

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

The last case above is what I want to get working. How can I add isInstance to instances, not just functions? And to all javascript gurus out there, are there any improvements to my code (the inherit method, maybe)?

Thanks.

4

3 回答 3

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(),但由于两者protoShape共享相同的prototype属性,JavaScript 无法区分。

您通常看不到原型链(尽管 Firefox 和 WebKit 通过属性使其可用__proto__),但它是 JS 中实际处理继承的方式;可见的 Function.prototype 属性仅用于在new-time 时设置原型链的初始状态。

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

Object.prototype.isInstance(c)= function() {
    return this instanceof c;
}

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

我的代码有什么改进(也许是继承方法)?

我喜欢你的继承方法,它是创建对象系统的更轻量级和 JavaScript 的方法之一。

除非您出于其他方便目的而需要它们,否则instanceof您可能会丢失parentand属性。constructor我会parent在构造函数上放置(所以它就像一个知道它的基类的子类),我会调用constructor其他东西(constructor在 Firefox 中已经调用了属性,但它并没有按照你的想法做,通常是最好的避免)。

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

function Square() {
    Shape.apply(this, arguments);
}
Square.inherit(Shape);
于 2009-10-03T17:32:09.030 回答
4

为什么需要这样做?JavaScript 没有严格的类层次结构的概念是有原因的:它真的做不到。您可能会得到一个在大多数情况下都有效的解决方案,但我不确定您是否能涵盖所有边缘情况。此外,由于 JavaScript 没有任何接口的概念,因此测试显式继承会导致高度耦合,并且似乎违反了SOLID 原则

解决此问题的更好(且更惯用)的方法是使用鸭子类型。只需测试您需要的方法是否存在,然后调用它。如有必要,请准备好捕获异常(无论如何您都应该这样做)。

于 2009-10-03T16:18:48.397 回答
1

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

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

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

然后您可以将其调用为

isInstance(obj2, Object2);
于 2009-10-03T16:52:55.333 回答