我试图在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>
是否属于任何已知的设计模式?
答案 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的评论,我正在更新我的回答(请参阅下面的评论,非常有用):
BaseClass
的原型时,不应创建DerivedClass
的新实例,请使用Object.create
(并在需要时将其填充)” BaseClass
并通过BaseClass.apply(this,arguments)
” 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.create
将Base
的原型“复制”为Derived
this.foo
未被复制到Derived
(因为它不是原型的一部分) - 请参阅下面第2点/ 有关Object.create
here的更多信息。
2 / BaseClass.apply(this, arguments)
如上所述,this.foo
实例无法使用Derived
。要使其可用,我们需要将Base
构造函数应用于Derived
构造函数..
因此Base
(this.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仅支持单继承)。
专用类通常称为子类,另一类通常称为父类。在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