La principale raison pour laquelle je le veux est que je veux étendre ma fonction d'initialisation.
Quelque chose comme ça:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
Je souhaite donc étendre une fonction comme j'étend une classe en PHP.
Et je voudrais aussi l’étendre à partir d’autres fichiers, alors par exemple, j’ai la fonction init originale dans main.js
et la fonction étendue dans extended.js
.
Avec une vision plus large de ce que vous essayez réellement de faire et du contexte dans lequel vous le faites, je suis sûr que nous pourrions vous donner une meilleure réponse que la réponse littérale à votre question.
Mais voici une réponse littérale:
Si vous attribuez ces fonctions à une propriété quelque part, vous pouvez envelopper la fonction d'origine et placer votre remplaçant sur la propriété:
// 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 voudrez probablement les mettre là pour faciliter ce qui précède. 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 existe de telles meilleures façons de le faire. Comme par exemple, fournir un moyen d’enregistrer les fonctions init
.
// 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 ce qui précède pourrait être écrit un peu plus compactement, mais je voulais utiliser des noms clairs comme publicSymbols
plutôt que mon habituel pubs
ou un littéral d'objet anonyme. Vous pouvez l'écrire. beaucoup plus compact si vous voulez avoir des fonctions anonymes, mais je ne me soucie pas beaucoup des fonctions anonymes .)
Il y a plusieurs façons de procéder, cela dépend de votre objectif. Si vous souhaitez simplement exécuter la fonction également et dans le même contexte, vous pouvez utiliser .apply()
:
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
Si vous voulez le remplacer par un nouveau init
, cela ressemblerait à ceci:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
Les autres méthodes sont excellentes mais elles ne conservent aucune fonction prototype attachée à init. Pour contourner ce problème, vous pouvez procéder comme suit (inspiré du message 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;
}) ();
Une autre option pourrait être:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
C'est très simple et direct. Regarde le code. Essayez de saisir le concept de base derrière l'extension javascript.
D'abord, étendons la fonction javascript.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
Vous pouvez étendre cette fonction en créant une fonction enfant de la manière suivante
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Maintenant, vous pouvez utiliser la fonction enfant comme suit,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Nous pouvons également créer une fonction Javascript en étendant des classes javascript, comme ceci.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Étendons cette classe avec la fonction enfant comme ceci,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Encore une fois, vous pouvez utiliser la fonction enfant comme suit pour obtenir un résultat similaire,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript est une langue très facile. Nous pouvons faire presque n'importe quoi. Joyeux JavaScript ... J'espère pouvoir vous donner une idée à utiliser dans votre cas.