在 Javascript 中实现 isInstance

发布于 2024-08-06 08:11:58 字数 1055 浏览 1 评论 0原文

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

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 专家来说,我的代码是否有任何改进(也许是继承方法)?

谢谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

写下不归期 2024-08-13 08:11:58

然后我需要定义一个 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

这就是为什么即使 Square.prototype 不是使用 new Shape 创建的,instanceof Shape 仍然可以工作;相反,它是由 new proto() 创建的,但由于 protoShape 共享相同的 prototype 属性, JavaScript 无法区分。

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

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

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

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

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

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

使用 instanceof 您可能会丢失 parentconstructor 属性,除非您出于其他方便目的需要它们。我会将 parent 放在构造函数上(所以它就像一个知道其基类的子类),并且我会调用 constructor 其他东西(已经有属性在 Firefox 中称为构造函数,但它不会按照您的想法执行,通常最好避免)。

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

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

I then need to define an isInstance function that would behave like Java's instanceOf or PHP's instanceof.

What is wrong with JavaScript's own instanceof?

Given your inherit function,

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

instanceof works by checking whether the given constructor's prototype property is in the instance's prototype chain. So eg.

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

This is why instanceof Shape works even though Square.prototype was not created using new Shape; instead it was created by new proto(), but since both proto and Shape share the same prototype property, JavaScript can't tell the difference.

You can't normally see the prototype chain (although Firefox and WebKit make it available through the __proto__ property), but it is the way inheritance is actually handled in JS; the visible Function.prototype property is only used to set up the initial state of the prototype chain at new-time.

How can I add isInstance to instances, not just functions?

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

I'm not sure this really gets you much though! And prototyping into Object is often considered in poor taste, as it affects literally every object and can confuse other scripts using Object for a lookup mapping.

are there any improvements to my code (the inherit method, maybe)?

I like your inherit method, it's one of the more lightweight and JavaScripty ways of making an object system.

With instanceof you could lose the parent and constructor properties, unless you wanted them for other convenience purposes. I'd put the parent on the constructor function though (so it's like a subclass knowing its base class), and I'd call constructor something else (there is already property called constructor in Firefox but it doesn't do what you think and is generally best avoided).

The only drawback I see is that you can't inherit the constructor function, so every time you make a new subclass you must write a constructor that calls the base constructor, even if your subclass's constructor does nothing at all:

function Square() {
    Shape.apply(this, arguments);
}
Square.inherit(Shape);
木格 2024-08-13 08:11:58

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

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

Why do you need to do this? JavaScript doesn't have a notion of a strict class hierarchy for a reason: it really can't be done. You can probably get to a solution that works most of the time, but I'm not sure you can cover all the edge cases. Additionally, since JavaScript doesn't have any notion of interfaces, testing for explicit inheritance leads to high coupling, and would seem to violate the SOLID principles.

A much better (and more idiomatic) way of approaching this problem is to use duck typing. Simply test for the existence of the method you need, and then call it. Just be prepared to catch an exception if necessary (which you should be doing anyway).

烟酒忠诚 2024-08-13 08:11:58

暂时将良好的设计论点放在一边并专注于您的问题,问题在于您将 isInstance() 设置为 Function 原型上的方法。这意味着属于函数的对象将具有它,而不是函数的对象(例如示例中的Object1Object2)则不会。

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

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

然后可以将其调用为

isInstance(obj2, Object2);

To leave the good design argument aside for a second and focus on your problem, the issue is that you set isInstance() to be a method on Function's prototype. This means Objects that are Functions will have it, while Objects that are not (such as Object1 and Object2 in your example) will not.

I suggest that instead of trying to implement it as a method, you have it be a static function:

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

You can then invoke it as

isInstance(obj2, Object2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文