使用JavaScript原型调用方法

mar*_*vpc 128 javascript overriding prototype

如果它被覆盖,是否可以从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
    }
};
Run Code Online (Sandbox Code Playgroud)

Chr*_*oph 200

我不明白你究竟想要做什么,但通常实现特定于对象的行为是这样做的:

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...*/);
}
Run Code Online (Sandbox Code Playgroud)

  • 不要在JS中使用"Class"字样,因为它会造成混淆.JavaScript中没有类 (10认同)
  • 我不明白为什么会有这么多的赞成票并被标记为正确.这仅覆盖基类的一个实例的行为,而不是所有子类的实例.因此,这不回答这个问题. (3认同)

小智 24

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

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

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

        //do something new

    }else{
        return this._do_base();
    }

};
Run Code Online (Sandbox Code Playgroud)

  • 这将创建无限递归. (11认同)
  • @JohanTidén`_do_base`存储对之前定义的任何函数的引用.如果没有,那么它将是'未定义'.JavaScript不是`make`-表达式永远不会像你建议的那样被懒惰地评估.现在,如果原型继承自*也*使用_do_base来存储它认为是基本类型的`do`的实现,那么你确实遇到了问题.所以,是的,如果使用这种方法,闭包将是一种更好的,继承安全的方式来存储对原始函数实现的引用 - 尽管这需要使用`Function.prototype.call(this)`. (10认同)
  • 我去过那里:无限递归. (3认同)

Mag*_*nar 16

我担心你的榜样不会像你想象的那样发挥作用.这部分:

this.do = function(){ /*do something*/ };
Run Code Online (Sandbox Code Playgroud)

覆盖了.的定义

MyClass.prototype.do = function(){ /*do something else*/ };
Run Code Online (Sandbox Code Playgroud)

由于新创建的对象已经具有"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
Run Code Online (Sandbox Code Playgroud)

在我看来,在javascript中处理对象,构造函数和继承的更清晰的方法.你可以在Crockfords Javascript中阅读更多内容:好的部分.

  • 确实非常好,但你不能真正将`base_do`称为函数,因为你在原来的`do`方法中失去了任何`this`绑定.因此,基本方法的设置有点复杂,特别是如果您想使用基础对象将其称为"this"而不是子对象.我会建议类似于`base_do.apply(me,arguments)`的东西. (3认同)

pho*_*lly 10

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

由此:

MyClass.prototype.doStuff.call(this /*, args...*/);
Run Code Online (Sandbox Code Playgroud)

对此:

this.constructor.prototype.doStuff.call(this /*, args...*/);
Run Code Online (Sandbox Code Playgroud)

  • 不要这样做,`this.constructor`可能并不总是指向'MyClass`. (6认同)

Ale*_*lva 5

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

function Person(){};
Person.prototype.say = function(message){
   console.log(message);
}
Run Code Online (Sandbox Code Playgroud)

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

var person = new Person();
person.say('hello!');
Run Code Online (Sandbox Code Playgroud)

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

Person.prototype.say('hello there!');
Run Code Online (Sandbox Code Playgroud)


小智 5

该解决方案使用 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());
Run Code Online (Sandbox Code Playgroud)