Javascript 特权函数继承

标签 javascript inheritance prototype

过去几周,我对 Javascript 继承进行了大量研究。首先,我想说我并不是在尝试在 Javascript 中实现基于类的继承,而是在尝试使用 Javascript 的原型(prototype)性质正确地模仿继承。这可能是在打败一匹死马,但我的问题是:

我有两个简单的函数:

function Animal(arg) {
    var a = arg;

    //privileged function has access to private variable
    this.sayHi = function(name) {
        // can access a here if needed
        console.log('Hi: ' + name);
    }
}

和:

function Person(arg) {
    this.sayHi = function(name) {
        super.sayHi(name + '!!!');
    };
}

Person.inheritsFrom(Animal);

以下是预期的结果:

var animal = new Animal('cow');
animal.sayHi('John'); // Hi: John

var person = new Person('adult');
person.sayHi('Fred'); // Hi: Fred!!!

我用于继承的“inheritsFrom()”方法如下所示:

Function.prototype.inheritsFrom = function(parent) {
    if(parent.constructor == Function) { //Normal Inheritance
        this.prototype = new parent;
        this.prototype.constructor = this;
        this.prototype.parent = parent.prototype;
    } else  { //Pure Virtual Inheritance
        this.prototype = parent;
        this.prototype.constructor = this;
        this.prototype.parent = parent;
    }
    return this;
}

这些是我的一些引用资料: http://phrogz.net/JS/classes/OOPinJS2.html http://www.crockford.com/javascript/inheritance.html https://medium.com/javascript-scene/common-misconceptions-about-inheritance-in-javascript-d5d9bab29b0a

很多好信息,仍然无法弄清楚如何继承如上所示的“特权”方法。我能够调用父类的特权方法。请参阅以下 JS fiddle :https://jsfiddle.net/jxjk5hm9/

非常感谢任何关于继承特权方法的指导,谢谢!

最佳答案

对此没有很好的解决方案。首先,

 this.prototype = new parent;

不是建立继承的好方法。而是使用

 this.prototype = Object.create(parent.prototype);

参见 Benefits of using `Object.create` for inheritance了解更多信息。

在子构造函数中,您必须调用父构造函数,将其应用于当前实例:

function Person(arg) {
    Animal.call(this, arg);
}

然后您必须遍历 Animal 附加到 this 的所有方法,并保留对它们的引用:

function Person(arg) {
    Animal.call(this, arg);
    var privilegedSuper = Object.keys(this)
      .filter(function(prop) { return typeof this[prop] === 'function'; }.bind(this))
      .reduce(function(obj, prop) { return (obj[prop] = this[prop]), obj; }.bind(this));
}

然后您可以在覆盖的方法中引用它:

function Person(arg) {
    Animal.call(this, arg);
    var privilegedSuper = Object.keys(this)
      .filter(function(prop) { return typeof this[prop] === 'function'; }.bind(this))
      .reduce(function(obj, prop) { return (obj[prop] = this[prop]), obj; }.bind(this));

    this.sayHi = function(name) {
      privilegedSuper.sayHi.call(this, name + '!!!');
    };
}

是否值得付出努力和复杂性?我不这么认为。

Function.prototype.inheritsFrom = function(parent) {
  if (parent.constructor == Function) { //Normal Inheritance
    this.prototype = Object.create(parent.prototype);
    this.prototype.constructor = this;
    this.prototype.parent = parent.prototype;
  } else { //Pure Virtual Inheritance
    this.prototype = parent;
    this.prototype.constructor = this;
    this.prototype.parent = parent;
  }
  return this;
}

function Animal(arg) {
  var a = arg;

  //privileged function has access to private variable
  this.sayHi = function(name) {
    // can access a here if needed
    console.log('Hi: ' + name + ' (and here is a: ' + a + ')');
  }
}

function Person(arg) {
  Animal.call(this, arg);
  var privilegedSuper = Object.keys(this)
    .filter(function(prop) {
      return typeof this[prop] === 'function';
    }.bind(this))
    .reduce(function(obj, prop) {
      return (obj[prop] = this[prop]), obj;
    }.bind(this), {});

  this.sayHi = function(name) {
    privilegedSuper.sayHi.call(this, name + '!!!');
  };
}
Person.inheritsFrom(Animal);

var animal = new Animal('cow');
animal.sayHi('John'); // Hi: John

var person = new Person('adult');
person.sayHi('Fred'); // Hi: Fred!!!

关于Javascript 特权函数继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31713291/

相关文章:

java - 利用继承来打印引用

c++ - 如何继承纯虚函数C++的实现

java - 为什么有时我们必须在 Android 中调用 super ?

javascript - Node.js:不能从另一个调用一个 Javascript 原型(prototype)方法?

javascript - 不能从 sinon stub 返回多个值

javascript - Discord.js 类型错误 : Cannot read property 'name' of undefined

javascript - 如何使用 Mocha 测试全局变量?

javascript - 在 JS 中将参数作为单独的参数传递

JavaScript 两个对象 - 相互覆盖

javascript - 如何在javascript中分别验证纬度和经度?