简体   繁体   English

如何通过原型在JavaScript中实现超级机制?

[英]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 . 如果thisCat (即使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM