使用JavaScript原型调用方法

时间:2009-02-18 12:21:17

标签: javascript prototype override

如果覆盖了JavaScript中的原型方法,是否可以调用基本方法?

MyClass = function(name){
    this.name = name;
    this.do = function() {
        //do somthing 
    }
};

MyClass.prototype.do = function() {  
    if (this.name === 'something') {
        //do something new
    } else {
        //CALL BASE METHOD
    }
};

14 个答案:

答案 0 :(得分:197)

我不明白你究竟想要做什么,但通常按照以下方式实现特定于对象的行为:

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

MyClass.prototype.doStuff = function() {
    // generic behaviour
}

var myObj = new MyClass('foo');

var myObjSpecial = new MyClass('bar');
myObjSpecial.doStuff = function() {
    // do specialised stuff
    // how to call the generic implementation:
    MyClass.prototype.doStuff.call(this /*, args...*/);
}

答案 1 :(得分:24)

一种方法是保存基本方法,然后从overriden方法调用它,就像这样

MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){  

    if (this.name === 'something'){

        //do something new

    }else{
        return this._do_base();
    }

};

答案 2 :(得分:16)

我担心你的榜样不会像你想象的那样奏效。这部分:

this.do = function(){ /*do something*/ };

覆盖

的定义
MyClass.prototype.do = function(){ /*do something else*/ };

由于新创建的对象已经具有“do”属性,因此它不会查找原型链。

Javascript中的经典继承形式是笨拙的,难以掌握。我建议使用Douglas Crockfords简单的继承模式。像这样:

function my_class(name) {
    return {
        name: name,
        do: function () { /* do something */ }
    };
}

function my_child(name) {
    var me = my_class(name);
    var base_do = me.do;
    me.do = function () {
        if (this.name === 'something'){
            //do something new
        } else {
            base_do.call(me);
        }
    }
    return me;
}

var o = my_child("something");
o.do(); // does something new

var u = my_child("something else");
u.do(); // uses base function

在我看来,在javascript中处理对象,构造函数和继承的更清晰的方法。您可以在Crockfords Javascript: The good parts中阅读更多内容。

答案 3 :(得分:10)

我知道这篇文章来自4年前,但由于我的C#背景,我一直在寻找一种方法来调用基类,而不必指定类名,而是通过子类上的属性获取它。所以我对Christoph's answer的唯一更改是

由此:

MyClass.prototype.doStuff.call(this /*, args...*/);

对此:

this.constructor.prototype.doStuff.call(this /*, args...*/);

答案 4 :(得分:4)

function NewClass() {
    var self = this;
    BaseClass.call(self);          // Set base class

    var baseModify = self.modify;  // Get base function
    self.modify = function () {
        // Override code here
        baseModify();
    };
}

答案 5 :(得分:4)

如果您定义这样的函数(使用OOP)

function Person(){};
Person.prototype.say = function(message){
   console.log(message);
}

有两种方法可以调用原型函数:1)创建一个实例并调用对象函数:

var person = new Person();
person.say('hello!');

,另一种方式是...... 2)直接从原型中调用函数:

Person.prototype.say('hello there!');

答案 6 :(得分:4)

替代方案:

// shape 
var shape = function(type){
    this.type = type;
}   
shape.prototype.display = function(){
    console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){ 
    // call implementation of the super class
    this.__proto__.display.apply(this,arguments);
}

答案 7 :(得分:4)

此解决方案使用Object.getPrototypeOf

TestA是超级getName

TestB是一个覆盖getName的孩子,但也有 getBothNames调用super getName版本以及child版本

function TestA() { this.count = 1; } TestA.prototype.constructor = TestA; TestA.prototype.getName = function ta_gn() { this.count = 2; return ' TestA.prototype.getName is called **'; }; function TestB() { this.idx = 30; this.count = 10; } TestB.prototype = new TestA(); TestB.prototype.constructor = TestB; TestB.prototype.getName = function tb_gn() { return ' TestB.prototype.getName is called ** '; }; TestB.prototype.getBothNames = function tb_gbn() { return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this); }; var tb = new TestB(); console.log(tb.getBothNames());

//.....
let tempstring : String = "hello world!" 
let tempnsstring : NSString = tempstring as NSString 
var tempnsdata : NSData! 
tempnsdata = tempnsstring.dataUsingEncoding(encoding) 
//.... 

答案 8 :(得分:2)

如果我理解正确,您希望始终执行Base功能,而其中一部分应该留给实现。

您可能会受到'template method'设计模式的帮助。

Base = function() {}
Base.prototype.do = function() { 
    // .. prologue code
    this.impldo(); 
    // epilogue code 
}
// note: no impldo implementation for Base!

derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }

答案 9 :(得分:1)

如果你知道你的超级名字,你可以这样做:

function Base() {
}

Base.prototype.foo = function() {
  console.log('called foo in Base');
}

function Sub() {
}

Sub.prototype = new Base();

Sub.prototype.foo = function() {
  console.log('called foo in Sub');
  Base.prototype.foo.call(this);
}

var base = new Base();
base.foo();

var sub = new Sub();
sub.foo();

这将打印

called foo in Base
called foo in Sub
called foo in Base

正如所料。

答案 10 :(得分:1)

ES5的另一种方法是使用Object.getPrototypeOf(this)

明确地遍历原型链
const speaker = {
  speak: () => console.log('the speaker has spoken')
}

const announcingSpeaker = Object.create(speaker, {
  speak: {
    value: function() {
      console.log('Attention please!')
      Object.getPrototypeOf(this).speak()
    }
  }
})

announcingSpeaker.speak()

答案 11 :(得分:0)

不,你需要在构造函数中给do函数和原型中的do函数使用不同的名称。

答案 12 :(得分:0)

此外,如果您想覆盖所有实例而不仅仅是那个特殊实例,那么这个实例可能有所帮助。

function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

myObj = new MyClass();
myObj.myMethod();

结果:

doing original
doing override

答案 13 :(得分:-1)

function MyClass() {}

MyClass.prototype.myMethod = function() {
  alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
  MyClass.prototype.myMethod_original.call( this );
  alert( "doing override");
};

myObj = new MyClass();
myObj.myMethod();