Cнова декоратор

Под впечатлением от этой и этой статей обновил декоратор.

Раньше он позволял только выполнить функцию перед или после другой функцией. Новая, расширенная версия, хоть и наложила ограничения на функции-обертки, имеет больше возможностей:
  1. подмена передаваемых аргументов;
  2. отмена выполнения;
  3. подмена возвращаемого значения.
Сам код, собственно (на github):
function decorate (initial, decorate_before, decorate_after) {
	return function () {
		var initial_call_result,
			updated_params,
			updated_result;

		if (typeof decorate_before === 'function') {
			updated_params = decorate_before.apply(this, arguments);
			if (!updated_params) {
				return;
			}
		}
		initial_call_result = initial.apply(this, updated_params || arguments);
		if (typeof decorate_after === 'function') {
			updated_result = decorate_after.apply(this, arguments);
		}
		return updated_result || initial_call_result;
	};
}
Из изменений: результат первой функции оберки используется как аргументы для вызова оригинальной функции.

Значит можно явно создавать свои варианты биндинга для функций. Например, чтобы при работе с jquery не указывать каждый раз контекст, можно создать обертку, в которой контекст явно задан:
var $iframe;
var iframe_context = $('iframe').eq(0);

$iframe = decorate($, function (selector, context) {
	return [selector, iframe_context];
});

// вместо явного указания:
var images = $('img', iframe_context);

// используем обертку
var images = $iframe('img');
Когда первая обертка не возвращает массив, считается, что оригинальную функцию не надо вызывать. Такой подход можно применять, когда надо подправить поведение плагина, но не хочется влезать в тонкости его реализации. При обновлении плагина не надо будет снова тормошить его внутренности в поисках изменений, так как код реализации и код допиливания будет разделен.

К тому-же некоторые баннерные сети до сих пор используют document.write для вставки ского кода. Если появляется желание обхитрить сеть и вставить их код асинхронно, то реализовать желание можно с помощью переписывания document.write. 
// отмена поведения метода плагина
plugin.method = decorate(plugin.method, function () {
	if (!ok_flag) {
		return;
	} else {
		return arguments;
	}
});

// вставка кода рекламного блока в обход document.write
document.write = decorate(document.write, function () {
	if (is_advert(arguments)) {
		on_advert_embeding.apply(this, arguments);
	} else {
		return arguments;
	}
});
Результат работы удобно подменять удобно при отладке кода. Когда часть системы уже готова, и известно как будет работать работать вторая часть, можно эмулировать ее поведение, подменой результатов ответа. Или же для юнит-тестирования частей системы.
get_products = decorate(get_products, function () {
	if (debug) {
		return;
	}
}, function () {
	if (debug) {
		return ['1111', '2222', '3333', '4444'];
	}
});
Share
Send
Popular