JavaScript中的覆盖函数

40

可能重复:
如何使用JavaScript原型调用基础方法

我想要继承一个对象并在JavaScript中覆盖函数。

从这个方法中,我想要调用基础方法。 在这种情况下,我继承了Person对象的reader对象,现在我想要覆盖getName函数,也就是说,在reader对象中,我首先想要调用Person对象上的函数,然后做一些更改。

<script>
    /* Class Person. */
    function Person(name) {
        this.name = name;
    }
    Person.prototype.getName = function() {
        return this.name;
    }

    var reader = new Person('John Smith');
    reader.getName = function() {
        // call to base function of Person, is it possible?
        return('Hello reader');
    }
    alert(reader.getName());
</script>
4个回答

41

Vincent已经回答了你的直接问题,但如果你想建立一个真正的继承层次结构,以便可以进一步扩展Reader,则可以按照下面的步骤进行操作。

创建你的人类:

function Person(name) {
    this.name = name;
}

Person.prototype.getName = function(){
    alert('Person getName called for ' + this.name);
    return this.name;
}

还要创建一个Reader类:

function Reader(name) {
    // Calls the person constructor with `this` as its context
    Person.call(this, name);
}

// Make our prototype from Person.prototype so we inherit Person's methods
Reader.prototype = Object.create(Person.prototype);

// Override Persons's getName
Reader.prototype.getName = function() {
    alert('READER getName called for ' + this.name);
    // Call the original version of getName that we overrode.
    Person.prototype.getName.call(this);
    return 'Something';
}
Reader.prototype.constructor = Reader;

现在我们可以重复类似的过程,使用 VoraciousReader 扩展 Reader:

function VoraciousReader(name) {
    // Call the Reader constructor which will then call the Person constructor
    Reader.call(this, name);
}

// Inherit Reader's methods (which will also inherit Person's methods)
VoraciousReader.prototype = Object.create(Reader.prototype);
VoraciousReader.prototype.constructor = VoraciousReader;
 // define our own methods for VoraciousReader
//VoraciousReader.prototype.someMethod = ... etc.

fiddle: http://jsfiddle.net/7BJNA/1/

Object.create:创建一个新对象,其原型是作为参数传递的对象。

Object.create(arg) 创建一个新对象,其原型是作为参数传递的对象。

Edit 这个答案发布已有数年之久,现在 JavaScript 支持使用 class 关键字。如果你来自像 Java 或 C++ 这样的语言,可以像期望的那样使用它。详见:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes


1
这应该是被选中的答案,它清晰地展示了JavaScript函数中使用原型实现虚拟继承的方法,而这在许多其他答案中都很模糊。 - daniel
想要用“古老”的JS版本解决一个类似的问题,而不使用类。问题是一个方法被定义为属性而不是原型上的方法。使用.call()是解决它的缺失部分,而不使用一些转译器并最终得到混乱的代码。 - Pjotr

35

由于您正确地在对象本身而不是原型上覆盖函数,因此您仍然可以使用该对象调用原型函数。

reader.getName = function() {
    var baseName = Person.prototype.getName.call(this);
    ...
}

6
如果ES5可用,可以使用Object.getPrototypeOf(this).getName.call(this);来使其更加动态。 - jAndy
2
我会使用Person.prototype.getName.apply(this, arguments),这样你就不会丢失任何参数。除非你特别不想传递参数。 - Dmitri R117

5

2
这是一种实现方式:

这是一种实现方式:

function Person(name) {
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}

var reader = new Person('John Smith');
reader.oldGetName = reader.getName;
reader.getName = function() {
//call to base function of Person , is it possible ?
    return this.oldGetName();
}
alert(reader.getName());​

http://jsfiddle.net/fXWfh/


Vincent的答案似乎比这个更整洁 - 可能是更好的方法... - Paddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接