Disons que j'ai var a = function() { return 1; }
. Est-il possible de modifier a
afin que a()
renvoie 2
? Peut-être en modifiant une propriété de l'objet a
, puisque chaque fonction est un objet ?
Mise à jour: Wow, merci pour toutes les réponses. Cependant, j'ai bien peur de ne pas chercher simplement à réaffecter une variable mais à éditer une fonction existante. Je réfléchis à la manière dont vous pouvez combiner des fonctions partielles dans Scala pour créer une nouvelle variable PartialFunction
. Je voudrais écrire quelque chose de similaire en Javascript et je pensais que la fonction existante pourrait peut-être être mise à jour, plutôt que de créer un tout nouvel objet Function
.
Vous pouvez faire toutes sortes de choses amusantes avec JavaScript, y compris les fonctions de redéfinition:
var a = function(){ return 1; }
alert(a()); //1
// keep a reference
var old = a;
// redefine
a = function(){
// call the original function with any arguments specified, storing the result
var originalResult = old.apply(old, arguments);
// add one
return originalResult + 1;
};
alert(a()); //2
Voila.
Edit: mis à jour pour afficher ceci dans un scénario plus fou:
var test = new String("123");
console.log(test.toString()); // logs 123
console.log(test.substring(0)); // logs 123
String.prototype.substring = function(){ return "hahanope"; }
console.log(test.substring(0)); // logs hahanope
Vous pouvez voir ici que même si "test" est défini en premier et que nous redéfinissons ensuite substring (), la modification s'applique toujours.
Note latérale: vous devriez vraiment reconsidérer votre architecture si vous faites cela ... vous allez confondre la merde d'un développeur médiocre dans 5 ans s'il cherche une définition de fonction qui est supposée revenir 1 , mais semble toujours revenir 2 ....
J'ai utilisé quelque chose comme ceci pour modifier une fonction existante dont la déclaration n'était pas accessible pour moi:
// declare function foo
var foo = function (a) { alert(a); };
// modify function foo
foo = new Function (
"a",
foo.toSource()
.replace("alert(a)", "alert('function modified - ' + a)")
.replace(/^function[^{]+{/i,"") // remove everything up to and including the first curly bracket
.replace(/}[^}]*$/i, "") // remove last curly bracket and everything after<br>
);
Au lieu de toSource (), vous pourriez probablement utiliser toString () pour obtenir une chaîne contenant la déclaration de la fonction. Certains appels à replace () pour préparer la chaîne à utiliser avec le constructeur de fonctions et pour modifier le source de la fonction.
var a = function() { return 1; }
alert(a()) // 1
a = function() { return 2; }
alert(a()) // 2
techniquement, vous perdez une définition de fonction et la remplacez par une autre.
Que diriez-vous de cela, sans avoir à redéfinir la fonction:
var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2
Vous voulez donc modifier le code d'une fonction directement, à la place, et pas simplement réaffecter une fonction différente à une variable existante.
Je déteste le dire, mais autant que j'ai pu le comprendre - et j'ai essayé -, cela ne peut être fait. Certes, une fonction est un objet et, à ce titre, elle a des méthodes et des propriétés qui peuvent être modifiées et remplacées sur l’objet même. Malheureusement, le corps de fonction n'en fait pas partie. Il n'est pas affecté à une propriété publique.
La documentation sur MDN répertorie les propriétés et les méthodes de l'objet fonction. Aucun d'entre eux ne nous donne l'occasion de manipuler le corps de la fonction de l'extérieur.
En effet, conformément à la spécification , le corps de la fonction est stocké dans la propriété interne [[Code]]
de l'objet fonction auquel il est impossible d'accéder directement.
Je m'en tiens à la solution de jvenema, dans laquelle je n'aime pas la variable globale "old". Il semble préférable de conserver l'ancienne fonction dans la nouvelle:
function a() { return 1; }
// redefine
a = (function(){
var _a = a;
return function() {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
}
})();
a() // --> gives 2
Toutes les solutions envisageables s’en tiennent à une "approche de recouvrement des fonctions" . La plus fiable d'entre elles semble être celle de rplantiko .
Un tel habillage de fonctions peut facilement être extrait. Le concept/modèle Lui-même pourrait être appelé "Méthode de modification". Son implémentation est bien Appartient à Function.prototype
. Il serait agréable d’être sauvegardé. Un jour par des modificateurs de méthode de prototype standard tels que before
, after
, around
, afterThrowing
et afterFinally
.
En ce qui concerne l'exemple susmentionné de rplantiko ...
function a () { return 1; }
// redefine
a = (function () {
var _a = a;
return function () {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
};
})();
a(); // --> gives 2
... et en utilisant [around]
, le code se transformerait en ...
function a () { return 1; }
console.log("a : ", a);
console.log("a() : ", a());
a = a.around(function (proceed, interceptor, args) {
return (proceed() + 1);
});
console.log("a : ", a);
console.log("a() : ", a());
Vous pouvez changer les fonctions comme d'autres objets
var a1 = function(){return 1;}
var b1 = a1;
a1 = function(){
return b1() + 1;
};
console.log(a1()); // return 2
// OR:
function a2(){return 1;}
var b2 = a2;
a2 = function(){
return b2() + 1;
};
console.log(a2()); // return 2
Ceci est un Exemple clair basé sur un timepicker de contrôle eworld.ui
www.eworldui.net
Avec un code TimePicker eworld.ui
où JavaScript est inaccessible de l'extérieur, vous ne pouvez trouver aucun fichier js associé à ces contrôles. Alors, comment pouvez-vous ajouter un événement onchange au timepicker?
Il existe une fonction js
appelée lorsque vous Select
un temps entre toutes les options proposées par le contrôle. Cette fonction est: TimePicker_Up_SelectTime
Vous devez d’abord copier le code dans cette fonction.
Evaluer ... quikwatch ...TimePicker_Up_SelectTime.toString()
function TimePicker_Up_SelectTime(tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
document.getElementById(tbName).value = selTime;
if(lblName != '')
document.getElementById(lblName).innerHTML = selTime;
document.getElementById(divName).style.visibility = 'hidden';
if(enableHide)
TimePicker_Up_ShowHideDDL('visible');
if(customFunc != "")
eval(customFunc + "('" + selTime + "', '" + tbName + "');");
eval(postbackFunc + "();");
}
À présent
En utilisant le code que vous avez enregistré avant de réaffecter le même code source mais en ajoutant ce que vous voulez.
TimePicker_Up_SelectTime = fonction (tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) { document.getElementById (tbName) .value = selTime; if (lblName! = '') document.getElementById (lblName) .innerHTML = selTime; document.getElementById (divName) .style.visibility = 'hidden'; if (enableHide) TimePicker_Up_ShowHideDDL ('visible'); if (customFunc! = "") eval (customFunc + "('" + selTime + "'," "+ tbName +" '); ");). eval (postbackFunc + "();");
>>>>>>> My function >>>>> RaiseChange(tbName);
}
J'ai ajouté ma fonction à la fonction pour pouvoir maintenant simuler un événement onchange lorsque je sélectionne une heure.
RaiseChange (...) pourrait être ce que vous voulez.
Absolument. Il suffit de lui attribuer une nouvelle fonction.
Ne pouvez-vous pas simplement le redéfinir plus tard? Quand vous voulez le changement, essayez simplement de le redéfinir comme suit:
a = function() { return 2; }
Si vous êtes en train de déboguer du javascript et que vous souhaitez voir comment les modifications apportées au code affectent la page, vous pouvez utiliser cette extension Firefox pour afficher/modifier les javascripts:
Exécutez l'extension JS firefox: https://addons.mozilla.org/en-US/firefox/addon/1729