我是Javascript的新手,这是关于继承的基本问题。
在我正在查看的网站中,向对象的原型添加新方法看起来非常简单。以下是他们展示的方法:
function Gadget(name, color) {
this.name = name;
this.color = color;
}
Gadget.prototype.getInfo = function() {
return 'Rating: ' + this.rating + ', price: ' + this.price;
};
然而,尝试复制同样的事情,我收到一个错误:
(function() {
window.onload = function() {
document.getElementById("main").innerHTML = getMessage();
}
function Animal(){
this.speak = function(){
return "I am a " + this.species + ", hear me " + this.sound + "!";
}
}
function Cat(){
this.__proto__ = new Animal();
this.species = "cat";
this.sound = "meow";
}
function getMessage(){
var cat = new Cat();
Cat.prototype.pounce = function() { return "Pounce!"}; //Adding prototype function here
var Boots = {};
Boots.__proto__ = new Cat();
return cat.speak() + '<br>' + Boots.pounce(); //Returning message that Boots.pounce() doesn't exist
}
})()
当我在调试窗口中查看Cat()对象时,它向我显示它没有属性“pounce”,Boots也没有。我在这做什么不起作用?
我认为自从我将该函数添加到对象的原型后,它将被添加到原型链中,从而继承。
非常感谢你的时间。
答案 0 :(得分:1)
__proto__
的行为从未标准化,只有legacy feature除外。
如果您使用Object.create
方法,则会有更好的时间。它将原型作为第一个参数,并返回一个使用该原型的对象。
如果使用Object.create
重写您的代码可能看起来更像这样。
function Animal() {
}
// you don't need to this, but it shows the prototype chain explicitly
Animal.prototype = Object.create(Object.prototype);
Animal.prototype.speak = function() {
return "I am a " + this.species + ", hear me " + this.sound + "!";
};
function Cat(){
this.species = 'cat';
this.sound = 'meow';
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.pounce = function() {
return "Pounce";
};
function getMessage() {
var cat = new Cat();
// you could dynamically add methods to the prototype, but the
// code will be faster if you declare the properties on the
// prototype, as early as possible
var Boots = new Cat();
return cat.speak() + '<br>' + Boots.pounce();
}
答案 1 :(得分:1)
这不是你如何使用原型,所以让我们以更标准化的方式重建它:
function Animal(){
this.species = 'Undefined';
this.sound = 'silence';
}
Animal.prototype = {
speak: function(){
return "I am a " + this.species + ", hear me " + this.sound + "!";
}
}
function Cat(){
Animal.apply(this);
this.species = 'cat';
this.sound = 'miauw';
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.pounce = function(){ return 'Pounce!'; }
那我们在这做了什么?我们首先创建一个function
,这通常被称为我们的构造函数。它主要用于设置存储的参数。然后我们创建一个原型object
,其中包含prototype
的方法(以及可能的原型参数)。
要创建Cat,我们创建另一个函数,然后将第一个function
应用于当前this
对象。这允许您继承原始构造函数在运行时所执行的所有操作。它基本上运行Animal的设置,但在我们的新Cat上。然后你做自定义的事情,比如将物种设置为'猫'。之后,我们将复制预先存在的Animal
原型,然后向其添加更多方法。
需要注意的是,所有这些都会进入prototype
密钥,不会 __proto__
。以双下划线开头的键和变量是你永远不应该触摸的东西,几乎从不使用它们 - 它们被认为是系统为你做的事情。您之前看到的__proto__
是以编程方式应用prototype
的结果,您可以在控制台中看到它,但它不是您应该搞的东西。
现在我们可以这样做:
// Ignore this bit, it's a repeat of the code above
// so I condensed it to a single line. Otherwise, exactly the same.
function Animal(){ this.species = 'Undefined'; this.sound = 'silence';}Animal.prototype = {speak: function(){return "I am a " + this.species + ", hear me " + this.sound + "!";}}; function Cat(){Animal.apply(this);this.species = 'cat';this.sound = 'miauw';}Cat.prototype = Object.create(Animal.prototype);Cat.prototype.pounce = function(){ return 'Pounce!'; }
// Helper function so the code reads clearly,
// but also writes to the snippet and adds the linebreaks
// and strong tags where necessary
function w(m,s){document.write((s?'<strong>':'')+(m?m:'')+(s?'</strong>':'')+'<br />');};
// Create our variables with the animal and the cat
var justAnAnimal = new Animal();
var pussInBoots = new Cat();
w( 'Speaking', true ); w();
w( 'justAnAnimal.speak()', true );
w( justAnAnimal.speak() );
w( 'pussInBoots.speak()', true );
w( pussInBoots.speak() );
w(); w('Pouncing', true); w();
w( 'justAnAnimal.pounce()', true );
// Use variable.method to check if the method exist
// if it does, then execute it and write that with variable.method()
// Otherwise print a different message so we know whats going on.
w(
(justAnAnimal.pounce && justAnAnimal.pounce())
|| 'Not every animal pounces (method does not exist for this instance)!'
);
w( 'pussInBoots.pounce()', true );
w(
(pussInBoots.pounce && pussInBoots.pounce())
|| 'Not every animal pounces (method does not exist for this instance)!'
);
w(); w('Checking the type of your animals using instanceof', true); w();
w( 'is justAnAnimal an Animal?', true );
w( justAnAnimal instanceof Animal ? 'Yes' : 'No' );
w( 'is justAnAnimal a Cat?', true );
w( justAnAnimal instanceof Cat ? 'Yes' : 'No' );
w( 'is pussInBoots an Animal?', true );
w( pussInBoots instanceof Animal ? 'Yes' : 'No' );
w( 'is pussInBoots a Cat?', true );
w( pussInBoots instanceof Cat ? 'Yes' : 'No' );
body {
font-family: 'Monaco', 'Courier MS', courier, monospace;
font-size: 10px;
}
strong {
color: #777;
margin-right: 20px;
display: inline-block;
font-weight: normal;
}
我发现这使得您的代码看起来更干净,因为一切都非常简单。构造函数,原型,一切都落入一个易于区分的模式,并且清晰可读。
在MDN上发表了一篇全面的文章:https://developer.mozilla.org/en/docs/Web/JavaScript/Inheritance_and_the_prototype_chain