1

我倾向于用 c 风格编写我的 Javascript “类”。

在 C#(例如)中,我们这样做

public class Parent {
    // stuff
}

public class Child : Parent {
    // Protected and public stuff from Parent will be accessible
}

在 JS 中,我通过使用proto找到了等价物,例如

var namespace = namespace || {};

namespace.Parent = function() {

    // Public variables
    self.pubVariable = "I am accessible";

    // Private variables
    var priVariable = "I'm not accessible outside of self";

    // ctor
    function self() {}

    return self;
}


namespace.Child = (function() {
    this.__proto__ = new namespace.Parent();

    // ctor
    function self() {}

    self.init = function() {
        // Prints the pubVariable
        console.log(pubVariable);
    };

    return self;

})($);

// Call it (statically)    
namespace.Child.init();

虽然这可行,但它仅适用于 Webkit 和 Mozilla。我知道这可以通过原型以某种方式实现,但无法弄清楚如何。任何建议表示赞赏。谢谢!

4

2 回答 2

6

对于父/子类,我会做这样的事情

// your parent class
var Parent = function() {

  // parent constructor
  console.log("parent constructor!");
  
  // some public properties
  this.foo = "foo";
  this.bar = "bar";

  // a private data member
  var secret = "123456";
};

// a parent function
Parent.prototype.something = function() {
  console.log("something!");
}

// your child class
var Child = function() {
  
  // call parent constructor
  Parent.call(this);    
  
  // child constructor
  console.log("child constructor!");

  // override bar
  this.bar = "override!";
};

// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});

示例用法

var c = new Child();
c.something();
// => parent constructor!
// => child constructor!
// => something!

c.foo //=> "foo"
c.bar //=> "override!"

如果您使用“命名空间”,则概念是相同的。


编辑

根据您的评论,这是并添加了演示

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };
var foo = new Foo();

// call our hello method
// this calls foo.__proto__.hello
foo.hello(); //=> "hello!"

// override `hello` method for this instance
foo.hello = function(){ return "こんにちは"; };

// call our hello method again
// this calls foo.hello because it is defined directly on our instance
// (it has a higher precedence in the lookup chain)
foo.hello(); //=> "こんにちは"

// remove the override
delete foo.hello;

// call our hello method again
// this goes back to calling foo.__proto__.hello
foo.hello(); //=> "hello!"

// remove the method prototype
delete Foo.prototype.hello

// call our hello method one last time
// spoiler: it's gone!
foo.hello(); //=> TypeError: Object [object Object] has no method 'hello'

如您所见,通过使用this.something = function(){};. 我个人更喜欢在原型上定义方法,因为它增加了灵活性。这样,原型就真的像蓝图一样工作。你得到所有预定义的行为;您可以根据需要进行修改并随时恢复为原始版本,所有这些都基于每个实例。


还有一件事

在上一个示例中,我们有一个原型方法和一个实例方法覆盖。有没有办法调用原始方法?让我们来看看!

var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };

var foo = new Foo();
foo.hello = function(){ return "こんにちは!"; }

// call override method
foo.hello(); //=> "こんにちは!"

// call original method
Foo.prototype.hello.call(foo); //=> "hello!"

// japanese just one more time...
foo.hello(); //=> "こんにちは!" 

这也可以,但我从来没有真正需要。我想这样做的好处是您不需要以这种方式了解原始课程:)

// call original method from the instance
foo.__proto__.hello.call(foo); //=> "hello!"

原型!

于 2013-06-23T17:39:55.483 回答
1

我想,你想要这个

// namespace
var namespace = namespace || {};

// Parent Class
namespace.Parent = function() {
    this.pubVariable = "I am accessible";
    var priVariable = "I'm not accessible outside of this";
}

// Child class
namespace.Child = function() {
    // namespace.Parent.call(this);
    this.init = function()
    {
        // returns Parent class' pubVariable
        // inherited by namespace.Child.prototype
        return this.pubVariable;
    }
};

// inherit Parent class
namespace.Child.prototype = new namespace.Parent();

var kid = new namespace.Child();
console.log(kid.init()); // I am accessible

如果您使用namespace.Parent.call(this),那么Child班级将拥有自己的副本,pubVariable但现在Child班级正在使用 Parent 的pubVariable.

另外,如果你想methods从父类与子类共享,那么你应该在父类的原型中添加方法,像这样

namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };

因此,当您将在这样的子类中继承它时

namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();

另一个子/子类

namespace.AnotherChild = function() { // ... };
namespace.AnotherChild.prototype = new namespace.Parent();

在这种情况下,两个子/子类都将使用aMethodInParent()其父类中的相同方法。

演示。

于 2013-06-23T17:59:57.657 回答