Внедрить JavaScript в функцию JavaScript - PullRequest
8 голосов
/ 21 января 2010

У меня странный вопрос: мне нужно вставить какой-нибудь javascript в другую функцию javascript. Я использую фреймворк, который заблокирован, поэтому я не могу изменить существующую функцию.

Что у меня есть, что-то вроде этого

function doSomething () { ... }

... ***

Я могу манипулировать *** (выше), но не могу изменить функцию doSomething ... Вместо этого мне нужно каким-то образом вставить несколько строк кода в конец кода doSomething.

Причина, по которой мне нужно это сделать, заключается в том, что пользовательская структура вызывает doSomething (), и это приводит к возвращению идентификатора с сервера, который мне нужно извлечь. На этот идентификатор ссылаются только внутри функции doSomething, поэтому я не могу его перехватить, пока я не введу код для этой функции (если я что-то пропустил).

Есть ли способ сделать это?

Ответы [ 7 ]

5 голосов
/ 21 января 2010

Псевдоним это.

var oldDoSomething = doSomething;
doSomething = function() {
  // Do what you need to do.
  return oldDoSomething.apply(oldDoSomething, arguments);
}
3 голосов
/ 22 января 2010

Спасибо за все ваши отзывы. Каждый ответ дал мне подсказку, и поэтому я нашел следующее решение.

<body>
<script type="text/javascript">
    var val;
    function doSomething(item1, item2) {
        var id = 3;
    }
    function merge() {
        var oScript = document.createElement("script");
        var oldDoSomething = doSomething.toString();
        oScript.language = "javascript";
        oScript.type = "text/javascript";
        var args = oldDoSomething.substring(oldDoSomething.indexOf("(") + 1, oldDoSomething.indexOf(")"));
        var scr = oldDoSomething.substring(oldDoSomething.indexOf("{") + 1, oldDoSomething.lastIndexOf("}") - 1);
        var newScript = "function doSomething(" + args + "){" + scr + " val = id; }";
        oScript.text = newScript;
        document.getElementsByTagName('BODY').item(0).appendChild(oScript);
    }

    merge();

</script>
<input type="button" onclick="doSomething();alert(val);" value="xx" />

2 голосов
/ 22 января 2010

Изменение функции при работе со строками исходного кода может быть довольно простым. Чтобы сделать это для конкретного экземпляра, попробуйте:

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);
}
2 голосов
/ 21 января 2010

Я не уверен, что вы подразумеваете под "заблокированным" - JavaScript интерпретируется вашим браузером. Даже если она была уменьшена или закодирована, вы все равно можете скопировать источник этой функции из источника на странице скрипта. В этот момент вы переназначаете исходную функцию на одну из ваших собственных разработок, которая содержит скопированный код и вашу собственную.

var id;
var myFunction = function() {
  // code copied from their source, which contains the variable needed

  // insert  your own code, such as for copying the needed value
  id = theirIDvalue;

  // return the value as originally designed by the function
  return theirValue;
};

theirObject.theirFunction = myFunction;
1 голос
/ 21 января 2010
function doSomething() { ... }
var oldVersionOfFunc = doSomething;
doSomething = function() {
    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args);
    // your added code here
    return retVal;
}

Это, кажется, вызывает ошибку (Слишком много рекурсии)

function doSomething(){ document.write('Test'); return 45; } 
var code = 'myDoSomething = ' + doSomething + '; function doSomething() { var id = myDoSomething(); document.write("Test 2"); return id; }';
eval(code)
doSomething();

Это работает для меня, даже если это безобразно.

0 голосов
/ 21 января 2010

Я не могу изменить функцию doSomething ... Вместо этого мне нужно каким-то образом вставить несколько строк кода в конец кода doSomething

Вставка нескольких строк в конец кода doSomething звучит как изменение функции doSomething для меня. К сожалению, я думаю, что вы облажались.

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

0 голосов
/ 21 января 2010

Функции являются значениями первого класса в Javascript, что означает, что вы можете хранить их в переменных (и на самом деле объявление именованной функции - это, по сути, назначение анонимной функции переменной).

Вы должны быть в состоянии сделать что-то вроде этого:

function doSomething() { ... }

var oldVersionOfFunc = doSomething;
doSomething = function() {

    var retVal = oldVersionOfFunc.apply(oldVersionOfFunc, args);

    // your added code here

    return retVal;
}

(Но я могу ошибаться. Мой JavaScript немного ржавый.;))

...