88 votes

Javascript: Étendre une Fonction

La raison principale pourquoi je veux c'est que je veux étendre ma fonction d'initialisation.

Quelque chose comme ceci:

// main.js

window.onload = init();
function init(){
     doSomething();
}

// extend.js

function extends init(){
    doSomethingHereToo();
}

Je tiens donc à exprimer une fonction comme je l'ai étendre une classe en PHP.

Et je tiens à exprimer à partir d'autres fichiers aussi, si par exemple j'ai l'original de la fonction init en main.js et la prolongation de la fonction en extended.js.

97voto

T.J. Crowder Points 285826

Avec une vue plus large de ce que vous êtes réellement en train de faire et le contexte dans lequel vous le faites, je suis sûr que nous pourrions vous donner une meilleure réponse que le littéral réponse à votre question.

Mais ici, c'est un littéral de réponse:

Si vous êtes à l'attribution de ces fonctions à une propriété quelque part, vous pouvez enrouler la fonction d'origine et de mettre votre remplacement sur la propriété à la place:

// Original code in main.js
var theProperty = init;

function init(){
     doSomething();
}

// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
    function extendsInit() {
        old();
        doSomething();
    }

    return extendsInit;
})(theProperty);

Si vos fonctions ne sont pas déjà sur un objet, vous souhaiterez probablement de les mettre là pour faciliter la ci-dessus. Par exemple:

// In main.js
var MyLibrary = (function() {
    var publicSymbols = {};

    publicSymbols.init = init;
    function init() {
    }

    return publicSymbols;
})();

// In extended.js
(function() {
    var oldInit = MyLibrary.init;
    MyLibrary.init = extendedInit;
    function extendedInit() {
        oldInit.apply(MyLibrary); // Use #apply in case `init` uses `this`
        doSomething();
    }
})();

Mais il y a ces meilleures façons de le faire. Comme par exemple, en fournissant un moyen de l'enregistrement d' init fonctions.

// In main.js
var MyLibrary = (function() {
    var publicSymbols = {},
        initfunctions = [];

    publicSymbols.init = init;
    function init() {
        var funcs = initFunctions;

        initFunctions = undefined;

        for (index = 0; index < funcs.length; ++index) {
            try { funcs[index](); } catch (e) { }
        }
    }

    publicSymbols.addInitFunction = addInitFunction;
    function addInitFunction(f) {
        if (initFunctions) {
            // Init hasn't run yet, rememeber it
            initFunctions.push(f);
        }
        else {
            // `init` has already run, call it almost immediately
            // but *asynchronously* (so the caller never sees the
            // call synchronously)
            setTimeout(f, 0);
        }
    }

    return publicSymbols;
})();

(Une grande partie de la ci-dessus pourrait être écrit un peu plus compacte, mais je voulais utiliser des noms comme publicSymbols plutôt qu'à mon habitude, pubs ou anonymes objet littéral. Vous pouvez écrire beaucoup plus compacte si vous voulez avoir les fonctions anonymes, mais je n'ai pas beaucoup de soins pour les fonctions anonymes.)

63voto

Nick Craver Points 313913

Il y a plusieurs façons d'aller à ce sujet, cela dépend de ce que votre objectif est, si vous voulez juste pour exécuter la fonction en tant que bien, et dans le même contexte, vous pouvez utiliser .apply():

function init(){
  doSomething();
}
function myFunc(){
  init.apply(this, arguments);
  doSomethingHereToo();
}

Si vous voulez la remplacer par une plus récente init, ça ressemble à ça:

function init(){
  doSomething();
}
//anytime later
var old_init = init;
init = function() {
  old_init.apply(this, arguments);
  doSomethingHereToo();
};

5voto

Ally Points 969

Les autres méthodes sont grands, mais ils ne préservent pas tout prototype des fonctions attachées à init. Pour obtenir autour de ce que vous pouvez effectuer les opérations suivantes (inspirées par la poste à partir de Nick Craver).

(function () {
    var old_prototype = init.prototype;
    var old_init = init;
    init = function () {
        old_init.apply(this, arguments);
        // Do something extra
    };
    init.prototype = old_prototype;
}) ();

-1voto

Devin G Rhode Points 3669

Utilisation extendFunction.js

init = extendFunction(init, function(args) {
  doSomethingHereToo();
});

Mais dans votre cas particulier, il est plus facile d'étendre le mondial onload de la fonction:

extendFunction('onload', function(args) {
  doSomethingHereToo();
});

En fait je aime vraiment votre question, c'est de me faire une réflexion sur les différents cas d'utilisation.

Pour les événements javascript, vous voulez vraiment ajouter et supprimer des gestionnaires - mais pour extendFunction, comment pourriez-vous faire plus tard suppression de la fonctionnalité? Je pourrais facilement ajouter un .revenir méthode à fonctions étendues, de sorte init = init.revert() serait de retour la fonction d'origine. Évidemment, cela pourrait conduire à un assez mauvais code, mais peut-être qu'il vous permet de faire quelque chose, sans toucher à l'étranger une partie de la base de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X