如何适当地扩展一些Javascript对象函数

How to properly extend some Javascript object function?

本文关键字:Javascript 对象 函数 何适当 扩展      更新时间:2023-09-26

我正在尝试创建一个邮箱插件(邮箱是一个基于雷鸟的邮件客户端),我有一个小问题。我不是一个Javascript专家,我不能理解这背后的问题…

我正在尝试从邮箱代码扩展一些对象函数。代码相当大,所以我尝试创建一个小示例来演示我的问题。以下代码是原始邮箱代码结构的示例:

FolderTreeView.prototype = {
    init: function FTV__init() {
        alert("init");
    },
    _ensureValidRow: function FTV__ensureValidRow(aRow) {
        alert("_ensureValidRow");
    },
    getCellProperties: function FTV_getCellProperties(aRow, aColumn, aProperties) {
        this._ensureValidRow(aRow);
    }
}
function FolderTreeView() {
    this._tree = null;
    this.init();
}
var gFolderView = new FolderTreeView();

我不能更改这段代码,因为当Postbox更新时,代码将恢复到原始源代码,维护它将是一件痛苦的事情。

下面是我自己的代码,试图扩展getCellProperties函数:

MyExtension = {
    init: function() {
        MyExtension.FolderIcon.load();
    },
    FolderIcon: {
        load: function() {
            var oGetCellProperties = gFolderView.getCellProperties;
            gFolderView.getCellProperties = function FTV_getCellProperties(aRow, aColumn, aProperties) {
                oGetCellProperties(aRow, aColumn, aProperties);
            }
            gFolderView.getCellProperties(null, null, null);
        }
    }
}

现在,oGetCellProperties正在调用原始函数,该函数反过来试图调用this._ensureValidRow,但失败了。错误控制台报告:

this._ensureValidRow is not a function

a.b()b中的this值设置为a。保存它不会:

a.b(); // sets `this` value inside `b` to `a`
var c = a.b;
c(); // does *not* set `this` value inside `b` to `a`

所以当你有:

var oGetCellProperties = gFolderView.getCellProperties;
// gFolderView is lost as `this` value

你宁愿要.bind.bind仅在较新的浏览器中可用,但在较旧的浏览器中有shims。

var oGetCellProperties = gFolderView.getCellProperties.bind(gFolderView);
// force `this` value

或者您可以在每次调用时设置this值,使用.call:

//                      `this`       argument1, ...
oGetCellProperties.call(gFolderView, aRow,      aColumn, aProperties);

问题的根源是函数调用function invocation -一些函数只是被调用,而不是在对象上调用

someFunction();

always, always设置this为全局对象。您可以通过使用call调用函数来解决这个问题,它允许您指定希望this等于

的内容。
gFolderView.getCellProperties = function FTV_getCellProperties(aRow, aColumn, aProperties) {
       oGetCellProperties.call(gFolderView, aRow, aColumn, aProperties);
}

apply也可以工作,但它希望它的参数作为数组传递,这在您的情况下稍微不太方便。

gFolderView.getCellProperties = function FTV_getCellProperties(aRow, aColumn, aProperties) {
       oGetCellProperties.apply(gFolderView, [aRow, aColumn, aProperties]);
}