[英]How to implement super mechanism in javascript through prototype?
I am struggling to understand the constructor invocation pattern in Javascript. 我正在努力了解Javascript中的构造函数调用模式。 I have a base object
Mammal
( would it be incorrect to use the term class ? ) and an inherited object Cat
. 我有一个基础对象
Mammal
(使用术语class是不正确的)和一个继承的对象Cat
。 In the following code the object Cat
correctly inherits from the Mammal object. 在以下代码中,对象
Cat
正确地从哺乳动物对象继承。
/*
Mammal base Object
*/
var Mammal = function(name) {
this.name = name;
}
Mammal.prototype.get_name = function() {
return this.name;
}
Mammal.prototype.says = function () {
return this.saying || '';
}
/*
Cat object
*/
var Cat = function (name) {
this.saying = "Meow";
this.name = name;
}
Cat.prototype.purr = function (number) {
var i =0, s='';
for ( i=0; i<number; i++)
if (s)
s +='-';
s+='r';
return s;
}
Cat.prototype = new Mammal();
console.log("Pseudo classical inheritance approach");
var mammal = new Mammal(" I am a mammal");
console.log("Who are you ? " + mammal.get_name());
console.log("What are you saying? " + mammal.says());
var cat = new Cat('I am a cat');
console.log("Who are you ? " + cat.get_name());
console.log("What are you saying? " + cat.says());
What I don't like in this pattern is how the constructor of the base object is used. 在这种模式下,我不喜欢的是如何使用基础对象的构造函数。 The object
Cat
does not reuse correctly the constructor of the base class Mammal
. 对象
Cat
不能正确地重用基类Mammal
的构造函数。 I would like to have a more flexibility. 我想拥有更大的灵活性。 Each time a
Cat
object is created, the constructor of the Mammal
object is invoked with no arguments. 每次创建
Cat
对象时,都会在没有参数的情况下调用Mammal
对象的构造函数。 I would like to use a mechanism similar to the "super" keyword in Java, so that when the constructor of Cat
is called with name
as parameter, also the constructor of Mammal
is called with name
as parameter. 我想使用一种类似于Java中“ super”关键字的机制,以便当以
name
为参数调用Cat
的构造函数时,也以name
为参数调用Mammal
的构造函数。
I tried to implement the Cat
constructor as follows : 我尝试如下实现
Cat
构造函数:
var Cat = function (name) {
this.saying = "Meow";
// Super (name);
this.prototype = new Mammal(name);
}
This does not work as expected. 这不能按预期方式工作。
this.prototype
is undefined. this.prototype
是未定义的。 why? 为什么? Why this approach is completely wrong?
为什么这种方法是完全错误的? does
this
point to the newly Cat
object? 做
this
点新Cat
对象?
I know, there are different ways to implement inheritance in javaScript, but I am wondering if there is a way to implement the super mechanism like in Java. 我知道,有多种方法可以在javaScript中实现继承,但是我想知道是否有一种方法可以像在Java中那样实现超级机制。
Thanks. 谢谢。 :D
:D
How about 怎么样
var Cat = function (name) {
this.saying = "Meow";
// Super (name);
Mammal.call( this, name );
}
Yes, I'm afraid that's not how you set up hierarchies. 是的,恐怕这不是您设置层次结构的方式。 It's close, but there are a couple of key issues.
即将结束,但是有几个关键问题。 (One of which — calling
new Mammal()
to create Cat.prototype
— is a very, very, very frequent error you see in a lot of blog posts and such.) (其中一个-调用
new Mammal()
创建Cat.prototype
是一个非常非常非常频繁的错误,您会在很多博客文章等中看到)
Here's a simple example of doing it correctly: 这是正确执行此操作的简单示例:
// A function to set up the link between a child and parent
function derive(Child, Parent) {
// `ctor` is a temporary function we use so we can get an object
// backed by `Parent.prototype` but without calling `Parent`.
function ctor() { }
// Borrow the prototype
ctor.prototype = Parent.prototype;
// Create an object backed by `Parent.prototype` and use it as
// `Child`'s prototype
Child.prototype = new ctor();
// Some housekeeping to make the prototype look like the ones
// the JavaScript engine creates normally.
Child.prototype.constructor = Child;
// Note: If we can rely on ES5 features, we could use
// `Object.create` instead of the `ctor` function.
}
// The parent constructor
var Mammal = function(name) {
this.name = name;
};
// Some stuff for its prototype
Mammal.prototype.get_name = function() {
return this.name;
};
Mammal.prototype.says = function () {
return this.saying || '';
};
// The child constructor
var Cat = function(name) {
Mammal.call(this, name);
this.saying = "Meow";
};
// Hook it up to the parent
derive(Cat, Mammal);
// Add some things to its prototype
Cat.prototype.purr = function (number) {
var i =0, s='';
for ( i=0; i<number; i++)
if (s)
s +='-';
s+='r';
return s;
};
If you're interested in doing inheritance hierarchies in JavaScript, you may find my Lineage
script useful. 如果您有兴趣在JavaScript中进行继承层次结构,您可能会发现我的
Lineage
脚本很有用。 You may or may not choose to use it, but it demonstrates how to set things up, a way to do calls to the parent's version of methods ("supercalls"), etc. In particular, this documentation page comparing using Lineage
to not using it shows how to do this without any helper script. 您可能会选择使用它,也可能不会选择使用它,但是它演示了如何进行设置,对父方法的版本(“超级调用”)进行调用的方法等。特别是, 本文档页面将使用
Lineage
与不使用它显示了如何在没有任何帮助脚本的情况下执行此操作。 But there's a reason I wrote a helper script to do it. 但是我写一个辅助脚本来这样做是有原因的。 :-)
:-)
this.prototype
is undefined, because no one defined it. this.prototype
是未定义的,因为没有人定义它。
Cat
is a function. Cat
是一种功能。 As such, it has a property prototype
. 因此,它具有属性
prototype
。 That's mandated by the ECMAScript standard. 这是ECMAScript标准强制要求的。
this
is an object that is not a function. this
是一个不是功能的对象。 As such, the ECMAScript standard does not mandate that it has a prototype
property. 因此,ECMAScript标准并不要求其具有
prototype
属性。
If this
is a Cat
(ie an object that was or is created using new Cat
), then it has, for the sake of specification , an internal [[Prototype]]
property which is a Mamal
. 如果
this
是Cat
(即使用new Cat
创建或创建的对象),则出于规范目的 ,它具有内部[[Prototype]]
属性,该属性为Mamal
。 But this mamal is not accessible directly (as implied by the word internal ). 但是,这种哺乳动物无法直接访问(如内部一词所暗示)。 When you say
var maru = new Cat()
, then maru.[[Prototype]]
is linked to Cat.prototype
. 当您说
var maru = new Cat()
, maru.[[Prototype]]
链接到Cat.prototype
。 That's how maru
knows about future methods of mamals. 这就是
maru
对未来的哺乳动物方法的了解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.