10

別のJavaScript関数にJavaScriptを挿入する必要があるという奇妙な質問があります。ロックされているフレームワークを使用しているため、既存の機能を変更できません。

私が持っているのはこのようなものです

関数doSomething(){...}

... ***

***(上記)を操作することはできますが、doSomething関数を変更することはできません...代わりに、doSomethingコードの最後に数行のコードを挿入する必要があります。

これを行う必要がある理由は、カスタムフレームワークがdoSomething()を呼び出すため、抽出する必要のあるIDがサーバーから返されるためです。このIDは、doSomething関数内でのみ参照されるため、その関数にコードを挿入しない限り、それをキャッチすることはできません(何かを見逃していない限り)。

これを行う方法はありますか?

4

7 に答える 7

6

エイリアスします。

var oldDoSomething = doSomething;
doSomething = function() {
  // Do what you need to do.
  return oldDoSomething.apply(oldDoSomething, arguments);
}
于 2010-01-21T12:05:57.397 に答える
4

ソース コード文字列を操作して関数を変更するのは、非常に簡単です。特定のインスタンスに対してそれを行うには、次を試してください。

eval(doSomething.toString().replace(/}\s*$/, ' return id; $&'));

doSomethingIDを返すようになりました。私は通常、 のファンではありませんが、ローカル変数にアクセスする必要があるためeval、通常のアスペクト指向プログラミング手法はここでは適用されません。

すでに値が返されている場合doSomethingは、本体を でラップしてみてくださいtry ... finally

eval(doSomething.toString()
    .replace(/^function *\w* *\([^)]*\) *{/, '$& try {')
    .replace(/}\s*$/, '} finally { window.someID = id; } $&')
);

これを関数に変換するには、コードをグローバル スコープで評価する必要があります。もともと、この回答はwithのスコープを変更するために を使用しevalていましたが、これは現在ブラウザーでは機能しません。代わりに、.callのスコープを に変更するために使用されevalますwindow

(function () {
    var begin = /^function\s*\w*\s*\([^)]*\)\s*{/,
        end = /}\s*$/;

    function alter(func, replacer) {
        var newFunc = replacer(func.toString());
        eval.call(window, newFunc);
    }

    function insertCode(func, replacer, pattern) {
        alter(func, function (source) { 
            return source.replace(pattern, replacer);
        });
    };

    /* Note: explicit `window` to mark these as globals */
    window.before = function (func, code) {
        return insertCode(func, '$& ' + code, begin);
    };

    window.after = function (func, code) {
        return insertCode(func, code + ' $&', end);
    };

    window.around = function (func, pre, post) {
        /* Can't simply call `before` and `after`, as a partial code insertion may produce a syntax error. */
        alter(func, function(source) {
            return source
                .replace(begin, '$& ' + pre)
                .replace(end, post + ' $&');
        });
    };
})();
...
after(doSomething, 'return id;');
/* or */
around(doSomething, 'try {', '} finally { window.someID = id; }');

変数にバインドされたメソッドと無名関数を書き直したい場合は、次のように変更alterします。

...
    function alter(func, replacer) {
        var newFunc = replacer(eval('window.' + funcName).toString());
        eval.call(window, newFunc);
    }
...
function Foo() {}
Foo.prototype.bar = function () { var secret=0x09F91102; }
...
after('Foo.prototype.bar', 'return secret;');

関数の最初の引数が文字列になっていることに注意してください。グローバル スコープでアクセスできないメソッドを処理するために、さらなる改善が行われる可能性があります。

于 2010-01-22T02:35:29.007 に答える
3

フィードバックをお寄せいただきありがとうございます。それぞれの答えが手がかりを与えてくれたので、次の解決策を思いつきました。

<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" />

于 2010-01-22T01:21:49.020 に答える
2

「ロックされている」とはどういう意味かわかりません - JavaScript はブラウザによって解釈されます。縮小またはエンコードされている場合でも、スクリプトのページのソースからその関数のソースをコピーできます。その時点で、元の関数を独自の設計の 1 つに再割り当てします。この設計には、コピーしたコードと独自のコードが含まれています。

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;
于 2010-01-21T15:05:28.340 に答える
1
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();

醜い場合でも、これは私にとってはうまくいきます。

于 2010-01-21T12:16:28.897 に答える
0

関数はJavascriptのファーストクラスの値です。つまり、関数を変数に格納できます(実際、名前付き関数を宣言すると、基本的に無名関数が変数に割り当てられます)。

あなたはこのようなことをすることができるはずです:

function doSomething() { ... }

var oldVersionOfFunc = doSomething;
doSomething = function() {

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

    // your added code here

    return retVal;
}

(しかし、私は間違っている可能性があります。私のJavaScriptは少し錆びています。;))

于 2010-01-21T12:04:52.207 に答える
0

doSomething 関数を変更することはできません...代わりに、doSomething コードの最後に数行のコードを挿入する必要があります

doSomethingコードの最後に数行を挿入することは、doSomething関数を変更するように思えます。残念ながら、あなたはだめだと思います。

(私はこのすべてについて少しぼんやりしていますが、関数は、そのようなことを心配する人々が、JavaScript に隠されている情報を実装する方法だと思います。まさに、関数の外部からスコープにアクセスできないためです。)

于 2010-01-21T12:09:30.797 に答える