我正在用 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
我觉得 first 和 second 对象都应该说它们是 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 fiddle和 this 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/
我正在尝试覆盖Devise方法set_flash_message.设计文档涵盖如何overridecontrollersforthevarioussubmodules.但是这个特定的方法位于DeviseController中,所有模块的父类。文档(wiki和内联)没有说明如何实现这一点,所以我不确定如何最好地进行。我相信最好的方法是简单地重新打开类并根据需要修改方法,并且我在/lib中放置了一个文件来达到这个效果。然而,它似乎先于Devise被加载,导致错误涌现。NameErrorinDevise::RegistrationsController#newundefinedlocalva
假设我有一个包含3个模型的Rails应用程序,Person、Place和Thing。SayThing使用单表继承,所以有FancyThing和ScaryThing子类。然后是用map.resources:people,:places,:things定义的路线。所以FancyThings和ScaryThings没有Controller,ThingsController处理这两种类型。现在假设我需要有代码来显示任何具有指向它们的链接的列表。如果我有这段代码:如果项目是一个人或一个地方,这很好用,polymorphic_path负责生成正确的路线。但是,如果item是FancyThing或S
A类和B类是相同的:classA像这样用基类进行重构有什么区别:classBase与这样使用基本模块:moduleBasedeffooputs"foo"endendclassA一种方式优于另一种方式吗? 最佳答案 这两种方法之间存在根本区别,所有其他答案都缺失,那就是Rails对STI(单表继承)的实现:http://api.rubyonrails.org/classes/ActiveRecord/Base.html(找到“单表继承”部分)基本上,如果您像这样重构您的基类:classBase然后,您应该有一个名为“bases”的数据
我对Ruby还是很陌生(通读Pickaxe并将大部分时间花在irb上),现在我知道可以在Ruby中修补类,我想知道什么时候这样做是可以接受的,特别是修补Ruby的基类是否可以接受。例如:我回答了另一个Ruby问题here张贴者想知道如何从DateTime中减去小时数。由于DateTime类似乎没有提供此功能,因此我发布了一个答案,将DateTime和Fixnum类作为可能的解决方案进行了修补。这是我提交的代码:require'date'#Aplaceholderclassforholdingasetnumberofhours.#Usedsowecanknowwhentochangeth
也许我只是没有使用正确的Ruby术语(如果我是,请纠正我),但谷歌在这方面没有帮助我。我拥有的是一个扩展另一个类(称为BaseStoreController)的类(称为OrderController)。在BaseStoreController中,我定义了一个before_filter用于我的整个站点,除了我的OrderController。在这种非常特殊的情况下,我需要定义一个自定义的before_filter,它需要执行一些额外的逻辑,然后调用在我的BaseStoreController中定义的before_filter。我不知道该怎么做。这是我尝试过的方法,但“super”关键字似
当在构造函数上设置原型(prototype)时,instanceof运算符仅返回true,直到原型(prototype)被更改。为什么?functionSomeConstructorFunction(){}functionextendAndInstantiate(constructorFn){constructorFn.prototype={};//CanbeanyprototypereturnnewconstructorFn();}varchild1=extendAndInstantiate(SomeConstructorFunction);console.log(child1ins
这两种说法有什么区别?它们给出不同的输出(在googlechrome控制台中)。functionTest(){if(thisinstanceofTest){}else{returnnewTest();}}x=Test();测试{}functionTest(){if(!thisinstanceofTest){returnnewTest();}}x=Test();未定义头脑=困惑 最佳答案 问题是!在instanceof之前计算,因此它被视为:if((!this)instanceofTest){...}而且,无论!this是true还是
这article定义instanceof如下:Theinstanceofoperatortestswhetheranobjecthasinitsprototypechaintheprototypepropertyofaconstructor.这是一个公平的解释,在我从EloquentJavascript书中看到这段代码之前,生活一直很美好:functionTextCell(text){this.text=text.split("\n");}TextCell.prototype.minWidth=function(){returnthis.text.reduce(function(wid
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
我有这样的代码classAnimal{}classDogextendsAnimal{}classCatextendsAnimal{}classDonkeyextendsAnimal{}我想查看应用程序宇宙中的所有类,当我找到一个从Animal派生的类时,我想创建一个该类型的新对象并将其添加到列表中。这允许我添加功能而无需更新事物列表。所以我可以避免以下情况:varanimals=[];animals.push(newDog());animals.push(newCat());animals.push(newDonkey());PS:我不想向我的类添加额外的功能或显式调用它们。