我有一个Javascript对象:
var Dog = function() {
this.speak = function() {
return 'woof'
}
this.trick = function() {
return 'sitting'
}
}
我想创建一个基于Dog的新对象Cat,但它有一个不同的speak
方法:
var Cat = ???
...
this.speak = function() {
return 'meow'
}
...
所以我最终可以这样做:
var tabby = new Cat();
tabby.speak() //returns 'meow'
tabby.trick() //returns 'sitting'
我对面向对象的Javascript'并且似乎无法在线找到反映我想要做的事情的示例,也不知道要搜索的关键字。
我认为这与我在Backbone中覆盖函数的方式类似,但这似乎有所不同:
var Cat = Dog.extend({
//the speak function below would override the one that returns 'woof'
speak: function() {
return 'meow'
}
});
感谢任何帮助!
(以上是我最终目标的简化版本 - 我想覆盖Rickshaw.Graph.Axis.X内的render
方法)
答案 0 :(得分:3)
通常在JavaScript中,我们将在原型上定义方法,而不是在实例上定义:
function Dog() {}
Dog.prototype.speak = function () {
return 'woof';
};
Dog.prototype.trick = function () {
return 'sitting';
};
在原型和实例上定义方法之间的区别在于原型允许您在将原型设置为同一对象的所有对象之间共享属性。您可以在此对象中定义共享的属性,原型对象也可以拥有自己的原型,从而创建原型链。
要创建一个简单的示例,让我们看一个简单的例子:
var foo = { bar: 1 };
// create a new object with its prototype set to `foo`
var baz = Object.create(foo);
console.log(foo.bar); // 1
console.log(baz.bar); // 1
// prototype properties and values are shared
foo.bar = 2;
console.log(foo.bar); // 2
console.log(baz.bar); // 2
// this is an instance property, so the property is no longer shared
baz.bar = 3;
console.log(foo.bar); // 2
console.log(baz.bar); // 3
如果你有一个原型继承系统,这就是你要做的:
function Dog() {}
Dog.prototype.speak = function () {
return 'woof';
};
Dog.prototype.trick = function () {
return 'sitting';
};
function Cat() {}
Cat.prototype = Object.create(Dog.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.speak = function () {
return 'meow';
};
请记住,如果在实例上定义属性,它将覆盖原型上的属性集,原型的原型等等。
如果您正在寻找具体情况的答案,您在实例上定义了方法(并且它不是内置构造函数 - 有些具有特殊行为),您需要做一些事情不同:
function Cat() {
Dog.call(this);
this.speak = function () {
return 'meow';
};
}
它的作用是为Dog
函数提供Cat
实例的当前对象,它可以在其上设置属性。这是通过将this
中Dog
的值设置为Cat
的实例来完成的,仅使用func.call(/* value of this */);
进行该调用。
答案 1 :(得分:2)
鉴于您目前的做法,您可以这样做:
var Dog = function() {
this.speak = function() {
return 'woof'
}
this.trick = function() {
return 'sitting'
}
}
var Cat = function() {
Dog.call(this)
this.speak = function() {
return 'meow'
}
}
虽然我们在这里没有使用原型继承。我们只是直接为对象分配自己的属性。这比使用共享的继承方法效率低。更不用说Cat
在speak
上创建Dog
方法,然后立即覆盖它。
var tabby = new Cat();
tabby.speak() //returns 'meow'
tabby.trick() //returns 'sitting'
答案 2 :(得分:2)
function Dog() {}
Dog.prototype.speak = function() {
return 'woof';
};
Dog.prototype.trick = function() {
return 'sitting';
};
function Cat(){}
Cat.prototype = Object.create(Dog.prototype);
Cat.prototype.speak = function() {
return 'meow';
};
var fluffy = new Cat();
fluffy.speak(); // 'meow'
fluffy.trick(); // 'sitting'
基本上,你想做一些谷歌搜索“原型继承”。
答案 3 :(得分:1)
与其他答案相同的概念,但这里是javascript秘密从谷歌关闭继承函数略微简化 - https://code.google.com/p/closure-library/source/browse/closure/goog/base.js#1578
var inherits = function(child, parent) {
function tmp () {};
tmp.prototype = parent.prototype;
child.superClass_ = parent.prototype;
child.prototype = new tmp;
child.prototype.constructor = child;
};
现在你可以
var Dog = function() {};
Dog.prototype.speak = function(){
return 'woof';
}
Dog.prototype.trick = function(){
return 'sitting';
}
var Cat = function(){};
inherits(Cat, Dog); //weird
Cat.prototype.speak = function(){
return "meow";
};
var HouseCat = function(){};
inherits(HouseCat, Cat);
HouseCat.prototype.speak = function(){
return "purr";
};
var dog = new Dog();
var cat = new Cat();
var houseCat = new HouseCat();
console.log(dog.speak()); //woof
console.log(cat.speak()); //meow
console.log(houseCat.speak()); //purr
console.log(houseCat.trick()); //sitting
console.log(cat instanceof Dog); //true
console.log(houseCat instanceof Cat); //true
console.log(houseCat instanceof Dog); //true
console.log(dog instanceof Cat); //false
console.log(cat instanceof HouseCat); //false