0

I want to overwrite a function, which is a method of a prototype of an Object. This method uses this internally. How can I overwrite that function but still keep this defined as the same object / value, as it has been in the original function?

The reasons I want to keep it are the following:

  • The original code supports extensions. I'd rather prefer writing an extension and add that to the code as intended by the authors of the original code, than changing the original code and having to build or install a modified version.
  • I need always perform some action before the original function is called. So I actually want to keep the original functionality, but want to add something before it. I think this would be "decorating" the function, like a decorator in Python.
  • The scope in code where I overwrite the function is not the same as where it is defined originally.

Here is some example code:

//original functions
var original_execute_cells = Jupyter.Notebook.prototype.execute_cells;

// decorating functions
function decorated_execute_cells(cell_indices) {
    console.log('EXTENSION: running decorated execute_cells function');
    return original_execute_cells(cell_indices);
}

// overwrite original functions
Jupyter.Notebook.prototype.execute_cells = decorated_execute_cells;

However, when I do that, I get a TypeError telling me that this is not defined, in the first line of the original function, which uses this.

The original source code of the function I am trying to overwrite can be found on github:

Notebook.prototype.execute_cells = function (indices) {
    if (indices.length === 0) {
        return;
    }

    var cell;
    for (var i = 0; i < indices.length; i++) {
        cell = this.get_cell(indices[i]);
        cell.execute();
    }

    this.select(indices[indices.length - 1]);
    this.command_mode();
    this.set_dirty(true);
};
Zelphir Kaltstahl
  • 4,331
  • 7
  • 46
  • 80

2 Answers2

0

I now did it with bind. The return statement becomes:

return original_execute_cells.bind(Jupyter.notebook)(cell_indices);

Where Jupyter.notebook is in my specific case the object this related to, when the Notebook object was build.

However, what @siebetman mentioned in the comment could also work and might even be more flexible in some situations. Also the link siebetman provided seems very useful in order to understand Javascript's this better.

Zelphir Kaltstahl
  • 4,331
  • 7
  • 46
  • 80
0

Why not just bind this?

var original_execute_cells = Jupyter.Notebook.prototype.execute_cells;
Jupyter.Notebook.prototype.execute_cells = function(cell_indices) {
    console.log('EXTENSION: running decorated execute_cells function');
    return original_execute_cells.bind(this)(cell_indices);
};