【问题标题】:How to implement super mechanism in javascript through prototype?javascript中如何通过prototype实现超级机制?
【发布时间】:2014-01-16 11:36:54
【问题描述】:

我很难理解 Javascript 中的构造函数调用模式。 我有一个基础对象Mammal(使用术语class会不正确吗?)和一个继承对象Cat。在下面的代码中,对象Cat 正确地继承自 Mammal 对象。

/* 
  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());

我不喜欢这种模式的基础对象的构造函数是如何使用的。对象Cat 没有正确重用基类Mammal 的构造函数。我希望有更大的灵活性。每次创建Cat 对象时,都会调用Mammal 对象的构造函数,不带任何参数。我想使用类似于Java中“super”关键字的机制,这样当Cat的构造函数以name为参数调用时,Mammal的构造函数也以name为参数调用.

我尝试如下实现Cat 构造函数:

  var Cat = function (name) {
      this.saying = "Meow";  
      // Super (name);
      this.prototype = new Mammal(name); 
    }

这没有按预期工作。 this.prototype 未定义。为什么?为什么这种方法是完全错误的? this 是否指向新的 Cat 对象?

我知道,在 javaScript 中实现继承有不同的方法,但我想知道是否有一种方法可以像在 Java 中那样实现超级机制。

谢谢。 :D

【问题讨论】:

    标签: javascript inheritance constructor prototype


    【解决方案1】:

    怎么样

    var Cat = function (name) {
      this.saying = "Meow";  
      // Super (name);
      Mammal.call( this, name );
    }
    

    【讨论】:

    • 使用这种机制,Cat 对象不会从 Mammal 对象继承。对吗?
    • 如果您保留其余代码,则可以。你只问了如何从继承类调用基类构造函数,所以我没有复制粘贴整个sn-p,我只修改了构造函数。
    【解决方案2】:

    是的,恐怕这不是您设置层次结构的方式。它很接近,但有几个关键问题。 (其中一个 - 调用 new Mammal() 创建 Cat.prototype - 是您在很多博客文章等中看到的非常、非常、非常频繁的错误。)

    这是一个正确操作的简单示例:

    // 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;  
    };
    

    如果您对在 JavaScript 中进行继承层次结构感兴趣,您可能会发现我的 Lineage script 很有用。您可能会或可能不会选择使用它,但它演示了如何设置,一种调用父级方法版本(“超级调用”)的方法等。特别是,this documentation page 使用 Lineage 进行比较不使用它展示了如何在没有任何帮助脚本的情况下执行此操作。但是我写了一个帮助脚本来做这件事是有原因的。 :-)

    【讨论】:

      【解决方案3】:

      this.prototype 未定义,因为没有人定义它。

      Cat 是一个函数。因此,它有一个属性prototype。这是 ECMAScript 标准规定的。

      this 是一个不是函数的对象。因此,ECMAScript 标准不要求它具有 prototype 属性。

      如果thisCat(即使用new Cat 创建的对象),那么为了规范,它有一个内部[[Prototype]] 属性这是Mamal。但是这种哺乳动物是不能直接接触到的(正如internal这个词所暗示的那样)。当您说var maru = new Cat() 时,maru.[[Prototype]]Cat.prototype 相关联。这就是maru 了解哺乳动物未来方法的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-12
        • 2013-10-29
        • 2016-04-11
        • 1970-01-01
        • 2015-03-23
        • 1970-01-01
        • 1970-01-01
        • 2018-11-17
        相关资源
        最近更新 更多