元のJSコードを変更せずに、既存のJSライブラリをカスタマイズしようとしています。このコードは、私がアクセスできるいくつかの外部JSファイルを読み込みます。私がやりたいのは、すべてをコピーして2番目のJSファイルに貼り付けることなく、元のファイルに含まれる機能の1つを変更することです。
たとえば、立ち入り禁止のJSには次のような機能があります。
var someFunction = function(){
alert("done");
}
その関数に何らかの形でJSコードを追加または追加できるようにしたいと思います。その理由は主に、元のタッチ不可能なJSでは関数が非常に巨大であり、そのJSが更新されると、上書きする関数が古くなるためです。
これが可能かどうかは完全にはわかりませんが、確認すると思いました。
someFunction
がグローバルに使用可能な場合、関数をキャッシュし、独自の関数を作成して、それを呼び出すことができます。
これがオリジナルの場合...
someFunction = function() {
alert("done");
}
あなたはこれをするだろう...
someFunction = (function() {
var cached_function = someFunction;
return function() {
// your code
var result = cached_function.apply(this, arguments); // use .apply() to call it
// more of your code
return result;
};
})();
.apply
を使用して、キャッシュされた関数を呼び出すことに注意してください。これにより、this
の期待値を保持し、引数の数に関係なく、個々の引数として渡された引数を渡すことができます。
最初に実際の関数を変数に保存します。
var oldFunction = someFunction;
次に、独自に定義します:
someFunction = function(){
// do something before
oldFunction();
// do something after
};
コードを呼び出す関数を作成してから、その関数を呼び出すことができます。
var old_someFunction = someFunction;
someFunction = function(){
alert('Hello');
old_someFunction();
alert('Goodbye');
}
関数を更新できるかどうかはわかりませんが、それがどのように参照されるかに応じて、代わりに新しい関数を作成できます。
var the_old_function = someFunction;
someFunction = function () {
/* ..My new code... */
the_old_function();
/* ..More of my new code.. */
}
また。ローカルコンテキストを変更する場合は、関数を再作成する必要があります。例えば:
var t = function() {
var a = 1;
};
var z = function() {
console.log(a);
};
いま
z() // => log: undefined
それから
var ts = t.toString(),
zs = z.toString();
ts = ts.slice(ts.indexOf("{") + 1, ts.lastIndexOf("}"));
zs = zs.slice(zs.indexOf("{") + 1, zs.lastIndexOf("}"));
var z = new Function(ts + "\n" + zs);
そして
z() // => log: 1
しかし、これは最も単純な例です。引数、コメント、戻り値を処理するには、まだ多くの作業が必要です。さらに、まだ多くの落とし穴があります。
toString | スライス | indexOf | lastIndexOf | 新しい関数
(user1106925が使用する)プロキシパターンを関数内に配置できます。以下で書いたものは、グローバルスコープにない関数、さらにはプロトタイプでも機能します。次のように使用します。
extender(
objectContainingFunction,
nameOfFunctionToExtend,
parameterlessFunctionOfCodeToPrepend,
parameterlessFunctionOfCodeToAppend
)
以下のスニペットでは、関数を使用してtest.prototype.doIt()を拡張していることがわかります。
// allows you to prepend or append code to an existing function
function extender (container, funcName, prepend, append) {
(function() {
let proxied = container[funcName];
container[funcName] = function() {
if (prepend) prepend.apply( this );
let result = proxied.apply( this, arguments );
if (append) append.apply( this );
return result;
};
})();
}
// class we're going to want to test our extender on
class test {
constructor() {
this.x = 'instance val';
}
doIt (message) {
console.log(`logged: ${message}`);
return `returned: ${message}`;
}
}
// extends test.prototype.doIt()
// (you could also just extend the instance below if desired)
extender(
test.prototype,
'doIt',
function () { console.log(`prepended: ${this.x}`) },
function () { console.log(`appended: ${this.x}`) }
);
// See if the prepended and appended code runs
let tval = new test().doIt('log this');
console.log(tval);