如何覆盖 javascript 库对象 this.function(arg, function(){

How to override javascript library object this.function(arg, function(){

我正在尝试覆盖 blessed-contrib tree module 中的函数。但是我认为我在对象继承方面遗漏了一些东西。任何帮助将不胜感激。

原代码:

function Tree(options) {
//...
  this.rows = blessed.list({
    top: 1,
    width: 0,
    left: 1,
    style: options.style,
    padding: options.padding,
    keys: true,
    tags: options.tags,
    input: options.input,
    vi: options.vi,
    ignoreKeys: options.ignoreKeys,
    scrollable: options.scrollable,
    mouse: options.mouse,
    selectedBg: 'blue',
  });

  this.append(this.rows);

  this.rows.key(options.keys, function() {
    var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
    if (selectedNode.children) {
      selectedNode.extended = !selectedNode.extended;
      self.setData(self.data);
      self.screen.render();
    }

    self.emit('select', selectedNode, this.getItemIndex(this.selected));
  });

//...

我试图在我自己的代码中覆盖 this.rows.key(options.keys, function() { 函数。我正在尝试执行类似以下的操作,但我不确定对象路径如何适用于在这种情况下最终属于 blessed-contrib.tree.list 类型的对象。

我的代码看起来像这样:

"use strict";
var blessed = require('blessed'),
    contrib = require('blessed-contrib');

//...

//create layout and widgets
var grid = new contrib.grid({rows: 1, cols: 2, screen: screen})

var tree =  grid.set(0, 0, 1, 1, contrib.tree,
    {
        style: {
        text: "red", fg: 'blue',
        selected: {
            bg: 'yellow', fg: 'white'
        }
    },
        // keys: ['+', 'space'],
        vi: true,
        template: { lines: true },
        label: 'Filesystem Tree'
    })

// monkeypatch contrib.tree.rows.key(options.keys, function() {}

// save the original
var old_tree_rows_key =  tree.rows.key;

//tree.rows.key = function(options_keys) {
tree.rows.key = function(options_keys) {
    var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];

    // handle items in options.keys array on my own for custom purposes
    // ...

    // Code I want commented out:
    // if (selectedNode.children) {
    //   selectedNode.extended = !selectedNode.extended;
    //   self.setData(self.data);
    //   self.screen.render();
    // }

    self.emit('select', selectedNode, this.getItemIndex(this.selected));
  };

//...

好的,谢谢@Bergi!他的线索让我找到了 javascript - Why is it impossible to change constructor function from prototype?。我在想我应该更深入地访问对象并且我不必复制整个构造函数 - 但我错了。

我的最终代码如下所示:

"use strict";

var blessed = require('blessed'),
    contrib = require('blessed-contrib'),
    Node = blessed.Node,
    Box = blessed.Box;

//...

// monkeypatch contrib.tree constructor to change keyhandler

// save the original
var old_tree =  contrib.tree.prototype;

//function Tree(options) {
contrib.tree = function(options) {

  if (!(this instanceof Node)) return new contrib.tree(options);

  var self = this;
  options = options || {};
  options.bold = true;
  this.options = options;
  this.data = {};
  this.nodeLines = [];
  this.lineNbr = 0;
  Box.call(this, options);

//...

  this.rows.key(options.keys, function() {
    var selectedNode = self.nodeLines[this.getItemIndex(this.selected)];
    // if (selectedNode.children) {
    //   selectedNode.extended = !selectedNode.extended;
    //   self.setData(self.data);
    //   self.screen.render();
    // }

    self.emit('select', selectedNode, this.getItemIndex(this.selected));
  });
//...
};

// restore binding
contrib.tree.prototype = old_tree;

var tree =  grid.set(0, 0, 1, 1, contrib.tree,
    {
        style: {
        text: "red", fg: 'blue',
        selected: {
            bg: 'yellow', fg: 'white'
        }
    },
        // keys: ['+', 'space'],
        vi: true,
        template: { lines: true },
        label: 'Filesystem Tree'
    })
//...