简单的Javascript继承示例

时间:2013-11-17 05:12:27

标签: javascript

我试图在JavaScript中实现简单的继承概念,而不使用任何外部库。这是我的代码。

<script>
    BaseClass = function () {
        this.doSomething = function () {
            console.log("base class");
        };
    };

    DerivedClass1 = function () {
        var bc = new BaseClass();
        bc.doSomething = function () {
            console.log("derived class");
        };
        return bc;
    };

    DerivedClass2 = function () {
        var bc = new BaseClass();
        return bc;
    }


    var cls1 = new DerivedClass1();
    cls1.doSomething();

    var cls2 = new DerivedClass2();
    cls2.doSomething();


</script>

是否属于任何已知的设计模式?

3 个答案:

答案 0 :(得分:3)

<强> TL; DR

var BaseClass = function (bar) {
    this.foo = bar;
};
BaseClass.prototype.doSomething = function () {
    console.log("from base class");
};

var DerivedClass = function () {
    BaseClass.apply(this, arguments);
};
DerivedClass.prototype = Object.create(BaseClass.prototype);
DerivedClass.prototype.doSomething = function () {

    BaseClass.prototype.doSomething.call(this);
    console.log("from derived class");
};

var cls1 = new DerivedClass('I am cls1');

cls1.doSomething();
// -> from base class
// -> from derived class

console.log(cls1.foo);
// -> "I am cls1"

<强>更新

感谢@HMR的评论,我正在更新我的回答(请参阅下面的评论,非常有用):

  1. “在设置BaseClass的原型时,不应创建DerivedClass的新实例,请使用Object.create(并在需要时将其填充)”
  2. “您还忘记初始化BaseClass并通过BaseClass.apply(this,arguments)
  3. 获取其实例变量的所有权

    1 /使用Object.create

    var BaseClass = function () {
        this.foo = 'bar';
    };
    BaseClass.prototype.doSomething = function () {
        console.log("base class");
    };
    
    var DerivedClass = function () {
    
    };
    DerivedClass.prototype = Object.create(BaseClass.prototype);
    

    备注

    • Object.createBase的原型“复制”为Derived
    • 公共财产this.foo 被复制到Derived(因为它不是原型的一部分) - 请参阅下面第2点/

    有关Object.create here的更多信息。

    2 / BaseClass.apply(this, arguments)

    如上所述,this.foo实例无法使用Derived。要使其可用,我们需要将Base构造函数应用于Derived构造函数..

    因此Basethis.foo,..)的所有privileged属性都会应用于Derived的新实例。

    var DerivedClass = function () {
    
        // Calls `Base` constructor with `Derived` context
        BaseClass.apply(this, arguments);
    };
    DerivedClass.prototype = Object.create(BaseClass.prototype);
    

    有关热门HMR's answer中javascript继承的更多详细信息。


    我留下原始答案进行比较&amp;教育目的。

    您的技术问题(虽然它可以按预期工作)是doSomething方法被复制到BaseClass的每个单独实例(因为它被声明为简单的public属性)。

    为了避免这种情况,并因此分享 doSomething方法,BaseClass所有BaseClass实例,您应该将其添加到var BaseClass = function () { }; BaseClass.prototype.doSomething = function () { console.log("base class"); }; doSomething }:

    // Derived Class 1
    var DerivedClass1 = function () {
    
    };
    DerivedClass1.prototype = new BaseClass();
    
    var cls1 = new DerivedClass1();
    cls1.doSomething();
    
    // -> "base class"
    
    
    // Derived Class 2
    var DerivedClass2 = function () {
    
    };
    DerivedClass2.prototype = new BaseClass();
    DerivedClass2.prototype.doSomething = function () {
        console.log("derived class (2)");
    };
    
    var cls2 = new DerivedClass1();
    cls2.doSomething();
    
    // -> "derived class (2)"
    

    您不会注意到最终结果有任何差异,但这样,parent方法“继承”,而不是复制。

    现在知道了,在Javascript中实现prototype

    DerivedClass

    Bonus ,如果您想从// Derived Class 3 var DerivedClass3 = function () { }; DerivedClass3.prototype = new BaseClass(); DerivedClass3.prototype.doSomething = function () { BaseClass.prototype.doSomething.call(this); console.log("derived class (3)"); }; var cls3 = new DerivedClass1(); cls3.doSomething(); // -> "base class" // -> "derived class (3)" 调用{{1}}方法:

    {{1}}

答案 1 :(得分:2)

最好在JavaScript中使用原型链进行继承。 在此示例中,您将为每个实例化重新定义对象。使用原型执行此操作更有效,因为您可以定义类型一次并重用定义。

这是somre更多信息: http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/

答案 2 :(得分:0)

继承是一种将类创建为一个或多个类的专用版本的方法(仅支持单继承)。
 专用类通常称为子类,另一类通常称为父类。在JavaScript中,您可以通过将父类的实例分配给子类,然后对其进行特化来完成此操作。在现代浏览器中,您还可以使用Object.create来实现继承。

  

注意:JavaScript不会检测子类prototype.constructor   (见Object.prototype),所以我们必须手动说明。见   问题Why is it necessary to set the prototype constructor?

在下面的示例中,我们将Student类定义为Person的子类 然后我们重新定义sayHello()方法并添加sayGoodBye()方法。

// Define the Person constructor
var Person = function(firstName) {
  this.firstName = firstName;
};

// Add a couple of methods to Person.prototype
Person.prototype.walk = function(){
  console.log("I am walking!");
};

Person.prototype.sayHello = function(){
  console.log("Hello, I'm " + this.firstName);
};

// Define the Student constructor
function Student(firstName, subject) {
  // Call the parent constructor, making sure (using call)
  // that "this" is set correctly during the call
  Person.call(this, firstName);

  // Initialize our Student-specific properties
  this.subject = subject;
}

// Create a Student.prototype object that inherits from Person.prototype.
// Note: A common error here is to use "new Person()" to create the
// Student.prototype. That's incorrect for several reasons, not least 
// that we don't have anything to give Person for the "firstName" 
// argument. The correct place to call Person is above, where we call 
// it from Student.
Student.prototype = Object.create(Person.prototype); // See note below

// Set the "constructor" property to refer to Student
Student.prototype.constructor = Student;

// Replace the "sayHello" method
Student.prototype.sayHello = function(){
  console.log("Hello, I'm " + this.firstName + ". I'm studying "
              + this.subject + ".");
};

// Add a "sayGoodBye" method
Student.prototype.sayGoodBye = function(){
  console.log("Goodbye!");
};

// Example usage:
var student1 = new Student("Janet", "Applied Physics");
student1.sayHello();   // "Hello, I'm Janet. I'm studying Applied Physics."
student1.walk();       // "I am walking!"
student1.sayGoodBye(); // "Goodbye!"

// Check that instanceof works correctly
console.log(student1 instanceof Person);  // true 
console.log(student1 instanceof Student); // true