Изменение функции при работе со строками исходного кода может быть довольно простым. Чтобы сделать это для конкретного экземпляра, попробуйте:
eval(doSomething.toString().replace(/}\s*$/, ' return id; $&');
Теперь doSomething
возвращает идентификатор. Обычно я не фанат eval
, но обычные методы аспектно-ориентированного программирования здесь не применимы из-за необходимости доступа к локальной переменной.
Если doSomething
уже возвращает значение, попробуйте:
eval(doSomething.toString().replace(/}\s*$/, ' window.someID = id; $&');
Чтобы превратить это в функцию, нам нужно, чтобы код оценивался в глобальной области видимости:
function insertCode(func, replacer, pattern) {
var newFunc = func.toString().replace(pattern, replacer);
with (window) {
eval(newFunc);
}
}
function after(func, code) {
return insertCode(func, function (old) { code + old }, /}\s*$/ );
}
...
after(doSomething, 'return id;');
Если вы хотите переписать методы и анонимные функции, связанные с переменными, измените insertCodeBefore
на:
function insertCode(funcName, replacer, pattern) {
var newFunc = eval('window.' + funcName).toString().replace(pattern, replacer);
eval('window.' + funcName + '=' + newFunc);
}
...
function Foo() {}
Foo.prototype.bar = function () { var secret=0x09F91102; }
...
after('doSomething', 'return id;');
after('Foo.prototype.bar', 'return secret;');
Обратите внимание, что первым аргументом функций теперь являются строки. Мы можем определить другие функции:
function before(func, code) {
return insertCode(func, function (old) {old + code}, /^function\s+\w+\([^)]*\)\s+{/);
}
function around(func, beforeCode, afterCode) {
before(func, beforeCode);
after(func, afterCode);
}