如何在JavaScript内置JavaScript类的子类中使用基类方法

How to use base class methods in a subclass of a Builtin JavaScript class in javascript

本文关键字:JavaScript 子类 基类 类方法 内置      更新时间:2023-09-26

例如,在c#中,我可以扩展框架类型并为我的类型分配表达式,它将保留基本类型的所有成员,但也有我的扩展方法。

我想从Range继承Sentence

注意建议的副本不适用于这里,因为Range不容易受到这些技术的影响。

我如何在javascript中实现这一点?我:

/* Namespace */
var WebPageReader = WebPageReader || {};
/* Classes */
WebPageReader.Sentence = function(range) {
    this.setStart(range.startContainer, range.startOffset); // bombs here
    this.setEnd(range.endContainer, range.endOffset);  
};
function test(){
  WebPageReader.Sentence.prototype = new Range();
  var dom = new WebPageReader.Dom();
  var s = new WebPageReader.Sentence(dom.GetSelectedRange());
  alert(s.endOffset)  ;
}
WebPageReader.Dom = function() {
  /* public methods */
  this.GetSelectedRange = function() {
    var sel;
    if (window.getSelection) {
      sel = window.getSelection();
      if ((sel.type == "Range" || allowCaretSelection) && sel.rangeCount) {
        return sel.getRangeAt(0);
      }
    }
    return null;
  }
}

这给出了错误:

Uncaught TypeError: Illegal invocation

尝试# 2

当我把代码改成这样:

/* Namespace */
var WebPageReader = WebPageReader || {};
/* Classes */
WebPageReader.Sentence = function(range) {
  Range.call(this);
};
function test(){
  WebPageReader.Sentence.prototype = new Range();
  var dom = new WebPageReader.Dom();
  var s = new WebPageReader.Sentence(dom.GetSelectedRange());
  alert(s.endOffset)  ;
}

我得到这个错误

Uncaught TypeError: Failed to construct 'Range': Please use 'new'操作符,此DOM对象构造函数不能作为函数调用。

您没有正确地子类化。你应该使用ES6类。

var WebPageReader = {
  Dom: function() {
    this.GetSelectedRange = function() {
      if (!window.getSelection) return null;
      return window.getSelection().getRangeAt(0);
    }
  },
  Sentence: class extends Range {
    constructor(range) {
      super();
      this.setStart(range.startContainer, range.startOffset);
      this.setEnd(range.endContainer, range.endOffset);
    }
  }
};
document.body.addEventListener('click', function() {
  var dom = new WebPageReader.Dom();
  var s = new WebPageReader.Sentence(dom.GetSelectedRange());
  console.log(s.endOffset);
});
Select text

它工作是因为super()将实例初始化为真正的Range。在ES5中,你只能做一些事情,比如让实例继承Range.prototype,这不足以成为一个真正的Range实例。Range方法只能在真正的Range实例上调用。

内置JavaScript类,如Error, ArrayRange不能仅使用ES5功能子类化。在支持从Range扩展的ES6类的浏览器中,可能工作,但这是一个脆弱的事情,我不觉得在这种情况下这样做是合理的。我认为你只需要助手方法,不需要子类化。您可以通过使用函数绑定语法操作符实现类似的外观:

// Would have been written
Sentence.prototype.additionalOperation = function() {
    return this.endContainer ...;
}
// can write this:
function additionalOperation() {
    return this.endContainer ...
}
// usage
// instead of:
new Sentence(range).additionalOperation();
// use this:
additionalOperation.call(range);
// or with bind syntax:
range::additionalOperation();