最近我读到了MDC中的JavaScript调用用法
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
下面显示的示例中的一个linke,我仍然不明白。
为什么他们在这里使用继承
Prod_dept.prototype = new Product();
这是必要的吗?因为在
中调用了超级构造函数Prod_dept()
无论如何,像这样
Product.call
这只是出于常见的行为吗?何时使用超级构造函数调用或使用原型链更好?
function Product(name, value){
this.name = name;
if(value >= 1000)
this.value = 999;
else
this.value = value;
}
function Prod_dept(name, value, dept){
this.dept = dept;
Product.call(this, name, value);
}
Prod_dept.prototype = new Product();
// since 5 is less than 1000, value is set
cheese = new Prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
car = new Prod_dept("honda", 5000, "auto");
感谢让事情更清楚
答案 0 :(得分:106)
真正问题的答案是你需要同时做到这两点:
因此,在设置继承时不应调用父的构造函数。仅在实例化从另一个继承的对象时。
Chris Morgan的答案几乎完成,遗漏了一个小细节(构造函数属性)。让我建议一种设置继承的方法。
function extend(base, sub) {
// Avoid instantiating the base class just to setup inheritance
// Also, do a recursive merge of two prototypes, so we don't overwrite
// the existing prototype, but still maintain the inheritance chain
// Thanks to @ccnokes
var origProto = sub.prototype;
sub.prototype = Object.create(base.prototype);
for (var key in origProto) {
sub.prototype[key] = origProto[key];
}
// The constructor property was set wrong, let's fix it
Object.defineProperty(sub.prototype, 'constructor', {
enumerable: false,
value: sub
});
}
// Let's try this
function Animal(name) {
this.name = name;
}
Animal.prototype = {
sayMyName: function() {
console.log(this.getWordsToSay() + " " + this.name);
},
getWordsToSay: function() {
// Abstract
}
}
function Dog(name) {
// Call the parent's constructor
Animal.call(this, name);
}
Dog.prototype = {
getWordsToSay: function(){
return "Ruff Ruff";
}
}
// Setup the prototype chain the right way
extend(Animal, Dog);
// Here is where the Dog (and Animal) constructors are called
var dog = new Dog("Lassie");
dog.sayMyName(); // Outputs Ruff Ruff Lassie
console.log(dog instanceof Animal); // true
console.log(dog.constructor); // Dog
在创建课程时,请参阅我的博文,了解更多语法糖。 http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
从Ext-JS和http://www.uselesspickles.com/class_library/复制的技术以及https://stackoverflow.com/users/1397311/ccnokes
的评论答案 1 :(得分:30)
执行此操作的理想方法是不执行Prod_dept.prototype = new Product();
,因为这会调用Product
构造函数。所以理想的方法是克隆它,除了构造函数,如下所示:
function Product(...) {
...
}
var tmp = function(){};
tmp.prototype = Product.prototype;
function Prod_dept(...) {
Product.call(this, ...);
}
Prod_dept.prototype = new tmp();
Prod_dept.prototype.constructor = Prod_dept;
然后在构造时调用超级构造函数,这就是你想要的,因为那时你也可以传递参数。
如果您查看Google Closure Library之类的内容,您会看到他们是如何做到的。
答案 2 :(得分:6)
如果您已在JavaScript中完成面向对象编程,您将知道可以按如下方式创建类:
Person = function(id, name, age){
this.id = id;
this.name = name;
this.age = age;
alert('A new person has been accepted');
}
到目前为止,我们的班级人员只有两个属性,我们将给它一些方法。一个干净的方法是这样做 使用它的'原型'对象。 从JavaScript 1.1开始,原型对象是在JavaScript中引入的。这是一个内置的对象 简化了向对象的所有实例添加自定义属性和方法的过程。 让我们使用'prototype'对象为我们的类添加2个方法,如下所示:
Person.prototype = {
/** wake person up */
wake_up: function() {
alert('I am awake');
},
/** retrieve person's age */
get_age: function() {
return this.age;
}
}
现在我们已经定义了我们的类Person。如果我们想要定义另一个名为Manager的类,它从Person继承了一些属性,该怎么办?在定义Manager类时,没有必要再次重新定义所有这些属性,我们可以将其设置为继承Person类。 JavaScript没有内置继承,但我们可以使用一种技术来实现继承,如下所示:
Inheritance_Manager = {};
//我们创建一个继承管理器类(名称是任意的)
现在让我们给继承类一个名为extend的方法,它接受baseClass和subClassas参数。 在extend方法中,我们将创建一个名为inheritance function inheritance(){}的内部类。我们之所以使用这种内心 class是为了避免baseClass和subClass原型之间的混淆。 接下来,我们将继承类的原型指向baseClass原型,如下面的代码: inheritance.prototype = baseClass。原型; 然后我们将继承原型复制到subClass原型中,如下所示:subClass.prototype = new inheritance(); 接下来要为我们的subClass指定构造函数,如下所示:subClass.prototype.constructor = subClass; 完成我们的子类原型设计后,我们可以指定接下来的两行代码来设置一些基类指针。
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
以下是我们的扩展功能的完整代码:
Inheritance_Manager.extend = function(subClass, baseClass) {
function inheritance() { }
inheritance.prototype = baseClass.prototype;
subClass.prototype = new inheritance();
subClass.prototype.constructor = subClass;
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
}
现在我们已经实现了继承,我们可以开始使用它来扩展我们的类。在这种情况下,我们将 将我们的Person类扩展为Manager类,如下所示:
我们定义Manager类
Manager = function(id, name, age, salary) {
Person.baseConstructor.call(this, id, name, age);
this.salary = salary;
alert('A manager has been registered.');
}
我们将其继承为Person
Inheritance_Manager.extend(Manager, Person);
如果您注意到,我们刚刚调用了Inheritance_Manager类的extend方法,并在我们的case中传递了subClass Manager,然后传递了baseClass Person。请注意,订单在这里非常重要。如果你交换它们,继承 如果有的话,将无法按预期工作。 另请注意,在实际定义subClass之前,需要指定此继承。 现在让我们定义我们的子类:
我们可以添加更多方法,如下所示。我们的Manager类将始终具有Person类中定义的方法和属性,因为它继承了它。
Manager.prototype.lead = function(){
alert('I am a good leader');
}
现在要测试它,让我们创建两个对象,一个来自Person类,另一个来自继承的类Manager:
var p = new Person(1, 'Joe Tester', 26);
var pm = new Manager(1, 'Joe Tester', 26, '20.000');
随时获取完整代码和更多评论: http://www.cyberminds.co.uk/blog/articles/how-to-implement-javascript-inheritance.aspx