2011-12-14 2 views
1

Я пытаюсь создать аддон почтового ящика (почтовый ящик - почтовый клиент на основе Thunderbird), и у меня небольшая проблема. Я далек от того, чтобы быть экспертом Javascript, и я не могу понять проблему за этим ...Как правильно расширить функцию Javascript?

Я пытаюсь расширить некоторую функцию объекта из кода почтового ящика. Код довольно большой, поэтому я попытался создать небольшой пример, чтобы продемонстрировать свою проблему. Следующий код представляет собой образец исходного Postbox код структуры:

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 

ответ

1

a.b() устанавливает значение this внутри b к 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); 
+1

Это отличный ответ; Мне нравятся дополнения ES5, но OP может захотеть проверить эту таблицу, чтобы узнать, поддерживаются ли его целевые браузеры. http://kangax.github.com/es5-compat-table/ –

+1

Это не для запуска в браузере как таковом, это расширение Postbox/Thunderbird. Я просто протестировал методы 'bind' и' call' в расширении и оба отлично работали :) –

1

корень вашей проблемы в том, что функции вызова с function invocation -Некоторые функции только будет вызван, в отличие от будучи ссылаться на объект

someFunction(); 

всегда, всегда сек et 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]); 
} 
Смежные вопросы