草庐IT

javascript oop、instanceof 和基类

coder 2024-05-14 原文

我正在用 JavaScript 设计一些类层次结构。到目前为止它工作正常,但我看不到如何确定一个对象是否是父类的“实例”。示例:

function BaseObject(name){
    this.name = name;

    this.sayWhoAmI = function(){
        console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
        console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
        console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
    };
}
function Derivation1(){
    BaseObject.apply(this, ['first derivation']);
}
function Derivation2(){
    BaseObject.apply(this, ['second derivation']);
}

var first = new Derivation1();
var second = new Derivation2();

first.sayWhoAmI(); 记录如下:

first derivation is a Derivation1 : true
first derivation is a Derivation2 : false
first derivation is a BaseObject : false

虽然 second.sayWhoAmI(); 记录了这个:

second derivation is a Derivation1 : false
second derivation is a Derivation2 : true
second derivation is a BaseObject : false

我觉得 firstsecond 对象都应该说它们是 BaseObject 的实例。

我知道 JavaScript 可能不是为此而制作的,但我想知道是否有办法实现它。

最佳答案

仅调用 Base.apply(...) 不会设置继承。 .apply 所做的只是将 this 设置为第一个参数,没有别的。调用父构造函数很重要,但这还不够。

您需要做的是正确设置原型(prototype)链。也就是说,您必须将 Derivation1.prototype 设置为继承自 Base.prototype 的内容。

由于构造函数的每个实例都继承自构造函数的原型(prototype),您将看到如下代码

Derivation1.prototype = new Base();

这是一个坏主意,您已经明白了原因:Base 期望参数设置实例特定的属性(在本例中为 name ).但我们不关心这些属性,因为稍后我们将在子构造函数中使用 Base.apply(this, ...) 初始化它们。

所以我们只需要一个继承自 Base.prototype 的对象,幸运的是,ECMASCript 5 定义了一个可以为我们做这件事的函数(polyfill):

 Derivation1.prototype = Object.create(Base.prototype);

这将创建一个继承自 Base.prototype 的新对象。现在,由于您用新对象替换了原始原型(prototype),因此必须设置 constructor 属性,使其正确指向 Derivation1:

Derivation1.prototype.constructor = Derivation1;

下面是一个完整的例子。也看看 this fiddlethis excellent answer by T.J. Crowder ,它基本上解释了相同的问题,但可能以更好的方式解释。


示例:

function BaseObject(name){
    this.name = name;
}

// move properties shared by all instances to the prototype!
BaseObject.prototype.sayWhoAmI = function() {
    console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
    console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
    console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
};

function Derivation1(){
    BaseObject.apply(this, ['first derivation']);
}

Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;

// some useless method of the child "class"
Derivation1.prototype.someOtherMethod = function() {
    return 42;
};

var first = new Derivation1();
first.sayWhoAmI();

关于javascript oop、instanceof 和基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11661078/

有关javascript oop、instanceof 和基类的更多相关文章

  1. ruby-on-rails - 覆盖 DeviseController 基类 - Rails 4,Devise 3 - 2

    我正在尝试覆盖Devise方法set_flash_message.设计文档涵盖如何overridecontrollersforthevarioussubmodules.但是这个特定的方法位于DeviseController中,所有模块的父类。文档(wiki和内联)没有说明如何实现这一点,所以我不确定如何最好地进行。我相信最好的方法是简单地重新打开类并根据需要修改方法,并且我在/lib中放置了一个文件来达到这个效果。然而,它似乎先于Devise被加载,导致错误涌现。NameErrorinDevise::RegistrationsController#newundefinedlocalva

  2. ruby-on-rails - 获取 Rails 中 STI 类基类的路由 - 2

    假设我有一个包含3个模型的Rails应用程序,Person、Place和Thing。SayThing使用单表继承,所以有FancyThing和ScaryThing子类。然后是用map.resources:people,:places,:things定义的路线。所以FancyThings和ScaryThings没有Controller,ThingsController处理这两种类型。现在假设我需要有代码来显示任何具有指向它们的链接的列表。如果我有这段代码:如果项目是一个人或一个地方,这很好用,polymorphic_path负责生成正确的路线。但是,如果item是FancyThing或S

  3. ruby-on-rails - 使用基类与基模块重构 ActiveRecord 模型 - 2

    A类和B类是相同的:classA像这样用基类进行重构有什么区别:classBase与这样使用基本模块:moduleBasedeffooputs"foo"endendclassA一种方式优于另一种方式吗? 最佳答案 这两种方法之间存在根本区别,所有其他答案都缺失,那就是Rails对STI(单表继承)的实现:http://api.rubyonrails.org/classes/ActiveRecord/Base.html(找到“单表继承”部分)基本上,如果您像这样重构您的基类:classBase然后,您应该有一个名为“bases”的数据

  4. ruby - 修补 Ruby 的基类(例如 Fixnum)是否可以接受? - 2

    我对Ruby还是很陌生(通读Pickaxe并将大部分时间花在irb上),现在我知道可以在Ruby中修补类,我想知道什么时候这样做是可以接受的,特别是修补Ruby的基类是否可以接受。例如:我回答了另一个Ruby问题here张贴者想知道如何从DateTime中减去小时数。由于DateTime类似乎没有提供此功能,因此我发布了一个答案,将DateTime和Fixnum类作为可能的解决方案进行了修补。这是我提交的代码:require'date'#Aplaceholderclassforholdingasetnumberofhours.#Usedsowecanknowwhentochangeth

  5. ruby-on-rails - 从子类中的重载方法调用基类方法 - 2

    也许我只是没有使用正确的Ruby术语(如果我是,请纠正我),但谷歌在这方面没有帮助我。我拥有的是一个扩展另一个类(称为BaseStoreController)的类(称为OrderController)。在BaseStoreController中,我定义了一个before_filter用于我的整个站点,除了我的OrderController。在这种非常特殊的情况下,我需要定义一个自定义的before_filter,它需要执行一些额外的逻辑,然后调用在我的BaseStoreController中定义的before_filter。我不知道该怎么做。这是我尝试过的方法,但“super”关键字似

  6. javascript - instanceof 运算符在继承链的后续更改时返回 false - 2

    当在构造函数上设置原型(prototype)时,instanceof运算符仅返回true,直到原型(prototype)被更改。为什么?functionSomeConstructorFunction(){}functionextendAndInstantiate(constructorFn){constructorFn.prototype={};//CanbeanyprototypereturnnewconstructorFn();}varchild1=extendAndInstantiate(SomeConstructorFunction);console.log(child1ins

  7. javascript - instanceof 的否定给出了意想不到的结果 - 2

    这两种说法有什么区别?它们给出不同的输出(在googlechrome控制台中)。functionTest(){if(thisinstanceofTest){}else{returnnewTest();}}x=Test();测试{}functionTest(){if(!thisinstanceofTest){returnnewTest();}}x=Test();未定义头脑=困惑 最佳答案 问题是!在instanceof之前计算,因此它被视为:if((!this)instanceofTest){...}而且,无论!this是true还是

  8. Javascript:仍然对 instanceof 运算符感到困惑 - 2

    这article定义instanceof如下:Theinstanceofoperatortestswhetheranobjecthasinitsprototypechaintheprototypepropertyofaconstructor.这是一个公平的解释,在我从EloquentJavascript书中看到这段代码之前,生活一直很美好:functionTextCell(text){this.text=text.split("\n");}TextCell.prototype.minWidth=function(){returnthis.text.reduce(function(wid

  9. javascript - 令人困惑的 "instanceof "结果 - 2

    functionFoo(){}functionBar(){}Bar.prototype=newFoo()console.log("Bar.prototype.constructor===Foo?"+(Bar.prototype.constructor===Foo))console.log("newBar()instanceofBar?"+(newBar()instanceofBar))=>Bar.prototype.constructor===Foo?true=>newBar()instanceofBar?true为什么“instanceof”的结果不是“false”,因为“const

  10. javascript - 查找 Javascript 应用程序中扩展基类的所有类 - 2

    我有这样的代码classAnimal{}classDogextendsAnimal{}classCatextendsAnimal{}classDonkeyextendsAnimal{}我想查看应用程序宇宙中的所有类,当我找到一个从Animal派生的类时,我想创建一个该类型的新对象并将其添加到列表中。这允许我添加功能而无需更新事物列表。所以我可以避免以下情况:varanimals=[];animals.push(newDog());animals.push(newCat());animals.push(newDonkey());PS:我不想向我的类添加额外的功能或显式调用它们。

随机推荐