Переопределение функции JavaScript при ссылке на оригинал
у меня есть функция, a()
, что я хочу переопределить, но также есть оригинал a()
выполняется в порядке, зависящем от контекста. Например, иногда, когда я создаю страницу, Я хочу переопределить ее следующим образом:
function a() {
new_code();
original_a();
}
а иногда Вот так:
function a() {
original_a();
other_new_code();
}
как мне это получить original_a()
в более-езда a()
? Это вообще возможно?
пожалуйста, не предлагайте альтернативы чрезмерной езде таким образом, я знаю многих. Я спрашиваю об этом конкретно.
11 ответов:
вы могли бы сделать что-то вроде этого:
var a = (function() { var original_a = a; if (condition) { return function() { new_code(); original_a(); } } else { return function() { original_a(); other_new_code(); } } })();
объявления
original_a
внутри анонимной функции он не загромождает глобальное пространство имен, но он доступен во внутренних функциях.как Nerdmaster упоминается в комментариях, не забудьте включить
()
в конце. Вы хотите вызвать внешнюю функцию и сохранить результат (один из двух внутренних функций) вa
, не хранить саму внешнюю функцию вa
.
на Прокси-шаблон может помочь вам:
(function() { // log all calls to setArray var proxied = jQuery.fn.setArray; jQuery.fn.setArray = function() { console.log( this, arguments ); return proxied.apply( this, arguments ); }; })();
выше заворачивает его код в функцию, чтобы скрыть "индикатора"-переменная. Он сохраняет setArray-метод jQuery в закрытии и перезаписывает его. Затем прокси-сервер регистрирует все вызовы метода и делегирует вызов оригиналу. Использование apply (this, arguments) гарантирует, что вызывающий объект не сможет заметить разницу между исходным и проксируемым методом.
Спасибо ребята прокси шаблон действительно помог.....На самом деле я хотел вызвать глобальную функцию foo.. На некоторых страницах мне нужно сделать некоторые проверки. Поэтому я сделал следующее.
//Saving the original func var org_foo = window.foo; //Assigning proxy fucnc window.foo = function(args){ //Performing checks if(checkCondition(args)){ //Calling original funcs org_foo(args); } };
Thnx это действительно помогло мне
вы можете переопределить функцию, используя конструкцию типа:
function override(f, g) { return function() { return g(f); }; }
например:
a = override(a, function(original_a) { if (condition) { new_code(); original_a(); } else { original_a(); other_new_code(); } });
Edit: исправлена опечатка.
передача произвольных аргументов:
a = override(a, function(original_a) { if (condition) { new_code(); original_a.apply(this, arguments) ; } else { original_a.apply(this, arguments); other_new_code(); } });
приведенные выше примеры НЕВЕРНО применяются
this
и передатьarguments
правильно для переопределения функции. Подчеркивать._ wrap () обертывает существующие функции, применяетсяthis
и передаетarguments
правильно. Смотрите: http://underscorejs.org/#wrap
ответ, который предоставляет @Matthew Crumley, заключается в использовании немедленно вызванных выражений функций, чтобы закрыть более старую функцию " a " в контексте выполнения возвращаемой функции. Я думаю, что это был лучший ответ, но лично я предпочел бы передать функцию " a " в качестве аргумента IIFE. Я думаю, что это более понятно.
var a = (function(original_a) { if (condition) { return function() { new_code(); original_a(); } } else { return function() { original_a(); other_new_code(); } } })(a);
У меня был какой-то код, написанный кем-то другим, и я хотел добавить строку в функцию, которую я не мог найти в коде. Поэтому в качестве обходного пути я хотел переопределить его.
ни одно из решений работал для меня.вот что сработало в моем случае:
if (typeof originalFunction === "undefined") { originalFunction = targetFunction; targetFunction = function(x, y) { //Your code originalFunction(a, b); //Your Code }; }
Я создал небольшой помощник для аналогичного сценария, потому что мне часто приходилось переопределять функции из нескольких библиотек. Этот помощник принимает "пространство имен" (контейнер) функции, имя функции, и главная функция. Он заменит исходную функцию в указанном пространстве имен на новую.
новая функция принимает исходную функцию в качестве первого аргумента, а исходные функции-в качестве остальных аргументов. Он будет сохранять контекст каждый раз. Он также поддерживает пустые и непустые функции.
function overrideFunction(namespace, baseFuncName, func) { var originalFn = namespace[baseFuncName]; namespace[baseFuncName] = function () { return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0))); }; }
использование например с Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) { // ... do stuff before base call baseFn(obj); // ... do stuff after base call });
Я не создавал никаких тестов производительности, хотя. Это может добавить некоторые нежелательные накладные расходы, которые могут или не могут быть большой проблемой, в зависимости от сценариев.
на мой взгляд, верхние ответы не читаются / не поддерживаются, а другие ответы неправильно связывают контекст. Вот читаемое решение с использованием синтаксиса ES6 для решения обеих этих проблем.
const orginial = someObject.foo; someObject.foo = function() { if (condition) orginial.bind(this)(...arguments); };
таким образом, мой ответ оказался решением, которое позволяет мне использовать переменную _this, указывающую на исходный объект. Я создаю новый экземпляр "квадрата", однако я ненавидел то, как" квадрат " генерировал его размер. Я думал, что это должно следовать моим конкретным потребностям. Однако для этого мне нужно было, чтобы квадрат имел обновленную функцию "GetSize" с внутренними элементами этой функции, вызывающими другие функции, уже существующие в квадрате, такие как этот.высота, вот это.GetVolume(). Но для того, чтобы сделать так что мне нужно было сделать это без каких-либо сумасшедших хаков. Так вот мое решение.
какой-то другой инициализатор объекта или вспомогательная функция.
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D( this.viewerContainer) var viewer = this.viewer; viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
функция в другом объекте.
updateToolbarButtons = function(viewer) { var _viewer = viewer; return function(width, height){ blah blah black sheep I can refer to this.anything(); } };