如何在jQuery / JavaScript中扩展返回的对象

时间:2017-03-08 12:36:16

标签: javascript jquery extend prototypal-inheritance

我想扩展/派生自jQuery' $.parseXML()函数返回的XML Document,以添加我自己的属性/函数。我是jQuery / JavaScript对象继承的新手。我试过在网上阅读,但不是"得到"它

在C#类中,我可以像这样编写一些东西(保持简单):

public class MyXmlDocument : XmlDocument
{
  public MyXmlDocument(string xmlText)
  {
    this.LoadXml(xmlText);
  }

  public string SomeVariable;
  ...

  public XmlNode FindCertainNode()
  {
    return this.SelectSingleNode("certain");
  }
  ...
}

MyXmlDocument xmlDoc = new MyXmlDocument(xmlText);
xmlDoc.AppendChild(...);  // XmlDocument method
XmlNode xmlNode = xmlDoc.FindCertainNode();  // MyXmlDocument method
etc.

我毫不犹豫地展示我的jQuery / JavaScript尝试因为我在海上,但我知道人们喜欢看到某些东西,所以请将其视为"我一直在玩的一些想法":

// One approach
function XMLDoc(xmlText)
{
  var parseXML = function (xmlText)
  {
    //var parser = new DOMParser();
    //var xmlDoc = parser.parseFromString(xmlText, "text/xml");
    var xmlDoc = $.parseXML(xmlText);
    return xmlDoc;
  };

  var findCertainNode = function ()
  {
    return this.find('certain');
  }

  return parseXML(xmlText);
}

// Another approach
var XMLDoc = $.extend({}, $.parseXML.prototype, {
  findCertainNode: function () {
    this.find('certain');
  }
});

我希望能够访问XML文档的现有功能以及我自己的扩展,如下所示:

var xmlDoc = new XMLDoc(xmlText);
var $xmlDoc = $(xmlDoc);
$xmlDoc.find('certain');  // jQuery method
$xmlDoc.findCertainNode();  // my additional method

我也知道我不清楚我的代码是应该返回纯JavaScript对象还是jQuery。我在想jQuery,所以我可以轻松地调用例如jQuery' s .find()等。

对我来说很重要的是,代码应该都包含在单个函数/对象或类似内容中,以便进行编辑/查看,就像我的尝试一样。

如果有人能够展示他们将如何实施C#模式,我认为这将回答我的问题,我应该非常感激。

编辑:解决方案

我正在将@ Karol的解决方案(https://stackoverflow.com/a/42672481/489865)标记为已接受的解决方案,因为他做了最多的工作来回答我的问题。

但是,我已经意识到从$.parseXML() / DOMParser().parseFromString()返回的对象不是一些特殊的" XML文档",它只是一个元素,并且因此没有特殊的方法。从它派生/继承它是不值得的,因此封装足够简单。我的模式如下:

var XMLDoc = function (xmlText) {
  this._xmlDoc = $.parseXML(xmlText);
};

$.extend(XMLDoc.prototype, {
    doc: this._xmlDoc,
    find: function (selector) {
      return $(this._xmlDoc).find(selector);
    },
    findCertain: function () {
      return $(this._xmlDoc).find("certain");
    },
    ...
});

var xmlDoc = new XMLDoc(xmlText);
xmlDoc.find('something');
xmlDoc.findCertainNode();

2 个答案:

答案 0 :(得分:1)

尝试:

var xmlDoc = new XMLDoc(xmlText);
$.extend( xmlDoc, {
  find: function(par){
          // your function
        }
});

答案 1 :(得分:1)

尝试这样做:

function XMLDoc(xmlText) { //constructor
  this._xmlDoc = $.parseXML(xmlText); //'_' is JS convention for private fields
}
XMLDoc.prototype = {
  findCertainNode: function() {
    return $(this._xmlDoc).find('certain');
  }
  /* other methods here */
}

var myXML = new XMLDoc('<a><certain /></a>')
myXML.findCertainNode(); //[<certain />]

或者与ES6语法相同:

class XMLDoc {
  constructor(xmlText) {
    this._xmlDoc = $.parseXML(xmlText);
  }
  findCertainNode() {
    return $(this._xmlDoc).find('certain');
  }
}

var myXML = new XMLDoc('<a><certain /></a>')
myXML.findCertainNode(); //[<certain />]

我认为jQuery的真正继承是不可能的,但是如果你真的想要有能力以C#方式使用它,你可以这样做:

Object.keys(Object.getPrototypeOf($())).forEach(function(key){
  XMLDoc.prototype[key] = function() {
    return $(this._xmlDoc)[key].apply(null, arguments);
  }
})

或者在ES6中:

Object.keys(Object.getPrototypeOf($())).forEach(key => {
  XMLDoc.prototype[key] = () => {
    return $(this._xmlDoc)[key](...arguments);
  }
})

然后你可以触发继承的所有jQuery方法。

如果您想重载其中的一些,请记住在上面的代码之后执行此重载。