【问题标题】:Implementing isInstance in Javascript在 Javascript 中实现 isInstance
【发布时间】:2009-10-03 16:05:59
【问题描述】:

我定义两个函数如何相互继承如下:

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 大师,我的代码是否有任何改进(可能是继承方法)?

谢谢。

【问题讨论】:

    标签: javascript inheritance instanceof


    【解决方案1】:

    然后我需要定义一个 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 和Shape 共享相同的prototype 属性,JavaScript 无法区分。

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

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

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

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

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

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

    使用instanceof,您可能会丢失parent 和constructor 属性,除非您出于其他方便的目的需要它们。我会把parent放在构造函数上(所以它就像一个知道它的基类的子类),我会调用constructor别的东西(在Firefox中已经有一个名为constructor的属性,但它没有'不要做你认为的事情,通常最好避免)。

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

    function Square() {
        Shape.apply(this, arguments);
    }
    Square.inherit(Shape);
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 啊,我想每个人都曾尝试用 javascript 编写自己的 OO 系统。这很有趣 - 真正展示了语言的真正灵活性。我认为没有人真正为生产而这样做 - 这完全是为了好玩。
      • +1 - 有趣的视角。但我仍然想知道如何做到这一点(即使,正如你所说,解决方案不能覆盖边缘)。
      【解决方案3】:

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

      我建议不要尝试将其作为方法来实现,而是将其设置为静态函数:

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

      然后你可以调用它

      isInstance(obj2, Object2);
      

      【讨论】:

        猜你喜欢
        • 2020-07-14
        • 2018-01-18
        • 2014-01-10
        • 2019-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-16
        • 1970-01-01
        相关资源
        最近更新 更多