J'essaie de personnaliser une bibliothèque JS existante sans modifier le code JS d'origine. Ce code est chargé dans quelques fichiers JS externes auxquels j'ai accès, et ce que j'aimerais faire, c'est modifier l'une des fonctions contenues dans le fichier d'origine sans copier-coller le tout dans le deuxième fichier JS .
Ainsi, par exemple, le JS hors limites pourrait avoir une fonction comme celle-ci:
var someFunction = function(){
alert("done");
}
J'aimerais pouvoir en quelque sorte ajouter ou ajouter du code JS à cette fonction. La raison en est principalement que dans le JS intouchable d'origine, la fonction est assez énorme et que si ce JS est mis à jour, la fonction avec laquelle je l'écrase sera périmée.
Je ne suis pas tout à fait sûr que ce soit possible, mais je me suis dit que je vérifierais.
Si someFunction
est globalement disponible, vous pouvez alors mettre la fonction en cache, créer la vôtre et la faire appeler par la vôtre.
Donc, si c'est l'original ...
someFunction = function() {
alert("done");
}
Tu ferais ça ...
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;
};
})();
Notez que j'utilise .apply
pour appeler la fonction en cache. Cela me permet de conserver la valeur attendue de this
et de transmettre tous les arguments qui ont été transmis comme arguments individuels, quel que soit le nombre.
d'abord stocker la fonction réelle dans une variable ..
var oldFunction = someFunction;
puis définissez le vôtre:
someFunction = function(){
// do something before
oldFunction();
// do something after
};
Vous pouvez créer une fonction qui appelle votre code, puis appelle la fonction.
var old_someFunction = someFunction;
someFunction = function(){
alert('Hello');
old_someFunction();
alert('Goodbye');
}
Je ne sais pas si vous pouvez mettre à jour la fonction, mais selon la manière dont elle est référencée, vous pouvez créer une nouvelle fonction à sa place:
var the_old_function = someFunction;
someFunction = function () {
/* ..My new code... */
the_old_function();
/* ..More of my new code.. */
}
Également. Si vous voulez changer le contexte local, vous devez recréer la fonction. Par exemple:
var t = function() {
var a = 1;
};
var z = function() {
console.log(a);
};
À présent
z() // => log: undefined
Ensuite
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);
Et
z() // => log: 1
Mais ce n'est que l'exemple le plus simple. Il faudra encore beaucoup de travail pour gérer les arguments, les commentaires et la valeur renvoyée. De plus, les pièges restent nombreux.
toString | tranche | indexOf | lastIndexOf | nouvelle fonction
Le modèle de proxy (tel qu'utilisé par l'utilisateur1106925) peut être placé dans une fonction. Celui que j'ai écrit ci-dessous fonctionne sur des fonctions qui ne sont pas dans la portée globale, et même sur des prototypes. Vous l'utiliseriez comme ceci:
extender(
objectContainingFunction,
nameOfFunctionToExtend,
parameterlessFunctionOfCodeToPrepend,
parameterlessFunctionOfCodeToAppend
)
Dans l'extrait ci-dessous, vous pouvez me voir en utilisant la fonction pour étendre 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);