Le fait que les fermetures de fonctions d'auto-référencement anonymes soient si répandues en JavaScript suggère-t-il que JavaScript est une spécification incomplète? Nous en voyons tellement:
(function () { /* do cool stuff */ })();
et je suppose que tout est une question de goût, mais cela ne ressemble-t-il pas à un kludge, alors que tout ce que vous voulez, c'est un espace de noms privé? JavaScript n'a-t-il pas pu implémenter des packages et des classes appropriées?
Comparez avec ActionScript 3, également basé sur ECMAScript, où vous obtenez
package com.tomauger {
import bar;
class Foo {
public function Foo(){
// etc...
}
public function show(){
// show stuff
}
public function hide(){
// hide stuff
}
// etc...
}
}
Contrairement aux convolutions que nous effectuons en JavaScript (ceci, à partir de la documentation de création du plugin jQuery ):
(function( $ ){
var methods = {
init : function( options ) { // THIS },
show : function( ) { // IS },
hide : function( ) { // GOOD },
update : function( content ) { // !!! }
};
$.fn.tooltip = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.tooltip' );
}
};
})( jQuery );
J'apprécie que cette question puisse facilement dégénérer en une diatribe sur les préférences et les styles de programmation, mais je suis en fait très curieux de savoir ce que vous en pensez des programmeurs chevronnés et si cela semble naturel, comme apprendre différentes idiosyncrasies d'une nouvelle langue ou kludgy , comme une solution de contournement à certains composants de base du langage de programmation qui ne sont tout simplement pas implémentés?
la source
Réponses:
La plupart des commentaires vont à l'encontre du mythe selon lequel «les prototypes sont des classes de pauvres», je vais donc simplement répéter que l'OO basé sur un prototype n'est en aucun cas inférieur à l'OO basé sur une classe.
L'autre point "un kludge quand tout ce que vous voulez c'est un espace de noms privé". Vous pourriez être surpris de savoir que Scheme utilise exactement le même kludge pour définir les étendues. Cela n'a pas empêché de devenir l'exemple archétypal de la portée lexicale bien faite.
Bien sûr, dans Scheme, le "kludge" est caché derrière les macros ....
la source
Tout d'abord, quelques choses:
Une autre façon de voir JavaScript est le 1 million et 1 choses que vous pouvez faire avec la fonction en tant que construction. Tout est là si vous le cherchez. Ce n'est jamais loin d'une fonction.
Cette chose de création de plug-in jQuery est horrible. Je ne sais pas pourquoi ils préconisent cela. Les extensions $ devraient être des éléments à usage général que $ a déjà assez bien couvert et non des méthodes de création de widget. C'est un outil de normalisation DOM-API. Son utilisation est mieux enfouie à l'intérieur de vos propres objets. Je ne vois pas l'intérêt de l'utiliser comme un référentiel de bibliothèque d'interface utilisateur complet.
Les packages sur le Web côté client sont inutiles
Ce que je n'aime pas personnellement à propos des packages sur le Web côté client, c'est que nous prétendons essentiellement que nous faisons quelque chose que nous ne faisons vraiment pas. Dans un post Web .NET et des tas de trucs horribles qui ne sont jamais supprimés de nos amis Java, je préfère penser à un morceau de HTML avec des ressources liées comme ce qu'il est vraiment. et ne pas essayer d'apaiser les développeurs d'applications OS résistantes à l'apprentissage de nouvelles choses en prétendant que c'est autre chose. Dans JS sur le Web côté client, rien n'est "importé" à moins de faire quelque chose d'horrible avec Ajax qui fonctionne dans l'ignorance de la mise en cache du navigateur, ce que oui, beaucoup ont essayé de faire. Tout ce qui compte pour le navigateur, c'est qu'il a été chargé et interprété ou non. Nous n'avons plus de code caché sur le client quelque part disponible pour une utilisation "juste au cas où" pour de bonnes raisons. # 1 étant que je viens de décrire un plug-in et des dépendances de plug-in de navigateur pour les applications Web comme un phénomène n'a généralement pas trop bien fonctionné. Nous voulons le web maintenant. Pas après la mise à jour d'Adobe ou de Sun pour la troisième fois cette semaine.
La langue a ce dont elle a besoin pour sa structure
Les objets JS sont hautement mutables. Nous pouvons avoir des arbres de branchement d'espaces de noms à tout degré que nous jugeons utile de le faire et c'est très facile à faire. Mais oui, pour tout ce qui est réutilisable, vous devez coller la racine de n'importe quelle bibliothèque à l'espace global. De toute façon, toutes les dépendances sont liées et chargées en même temps, alors à quoi bon faire autre chose? Le point d'éviter l'espace de noms global n'est pas que quelque chose soit mauvais. C'est que trop de choses sont mauvaises parce que vous courez le risque de collisions d'espace de noms ou d'écraser accidentellement les fonctionnalités du langage de base.
Ce n'est pas parce que c'est populaire que nous le faisons correctement
Maintenant, lorsque vous voyez cela partout dans une application Web côté client:
Le problème n'est pas que nous manquons d'outils pour structurer une application, le problème est que les gens ne valorisent pas la structure. Pour les sites jetables temporaires de 2-3 pages dans une agence de design, je n'ai pas vraiment de problème avec ça. Là où ça devient moche, c'est quand il faut construire quelque chose de maintenable, lisible et facile à modifier.
Mais lorsque vous arrivez à l'endroit où il est temps de simplement implémenter tous les objets et usines réutilisables et peut-être qu'un ou deux nouveaux vars temporaires pourraient se glisser dans ce processus, c'est une commodité.
Mais il existe des implémentations de JS avec des packages / modules
Gardez à l'esprit que dans Node.js, où de telles choses ont beaucoup plus de sens, ils ont des modules. JS, en supposant que nous pouvons éviter uber-config-hell qui empoisonne d'autres langages, est la seule chose dans l'équation et chaque fichier exécuté est sa propre portée isolée. Mais sur une page Web, la liaison d'un fichier js est elle-même l'instruction d'importation. Faire plus d'importations à la volée n'est qu'une perte de temps et de ressources, car obtenir les ressources nécessite beaucoup plus d'efforts que d'ajouter simplement des liens aux fichiers car vous en avez besoin en sachant qu'ils seront mis en cache dans un navigateur si une autre page en a besoin à nouveau. Il en va de même pour diviser l'espace global en faisant autre chose que de créer des fabriques d'objets adaptateurs comme jQuery ou des objets plus traditionnels qui couvrent un large sous-ensemble de tâches dans un domaine donné tout en occupant une place dans global. Là'http://wiki.ecmascript.org/doku.php?id=harmony:modules
Donc non, il n'y a rien de mal avec les invocateurs automatiques utilisés pour éviter la pollution globale des espaces de noms quand il y a une bonne raison d'utiliser de telles choses (le plus souvent il n'y en a pas). Et nous avons des propriétés équivalentes privées persistantes dans nos objets (définissez simplement une var dans le constructeur et ne l'exposez pas en tant que propriété).
Le fait que nous POUVONS faire de telles choses, cependant, est génial. Une utilisation intensive est un signe que les développeurs JS mûrissent peut-être encore, mais ce n'est pas un trou béant dans la langue pour quiconque n'essaie pas de forcer un paradigme dans le Web côté client qui n'a tout simplement pas de sens ici.
la source
L'autre chose qui vous manque, c'est que javscript doit être rétrocompatible. Si vous essayez d'introduire la syntaxe d'un package, cela pourrait vraiment casser le Web de manière folle. Ce serait mauvais! Doug Crockford en a parlé à différents moments et pourquoi les tentatives pour l'ajouter ont échoué.
la source
Oui, c'est un coup de coude.
Beaucoup de gens disent que "les prototypes ne sont pas inférieurs aux classes". Je ne suis pas d'accord, mais c'est une question de préférence. Mais ce n'est même pas le vrai problème avec JavaScript - le problème est qu'il a été initialement conçu comme un langage de script rapide et sale pour créer des choses comme des boutons animés. Au milieu des années 90, personne n'a jamais pensé que JavaScript serait invité à faire certaines des choses folles qu'il fait maintenant.
la source
Les fonctions auto-appelantes anonymes sont plus proches des modules que des classes. Il est ennuyeux que la valeur par défaut pour javascript soit de s'exécuter dans la portée globale. Le comité travaillant sur JS.next envisage sérieusement d'ajouter des modules, afin que vous ne déposiez pas vos variables locales dans la portée globale. Heureusement, les fonctions de Javascript ont une sémantique si pratique que nous pouvons utiliser une fonction anonyme comme portée privée avec une relative facilité.
Je ne vois pas du tout comment les classes entrent vraiment dans la discussion, sauf qu'elles sont la construction de portée de haut niveau dans de nombreuses langues. Une meilleure construction module / package / please-give-me-a-local-scope-so-i-don't-my-variables-in-the-global-environment serait très agréable à avoir.
la source
Vous voudrez peut-être jeter un œil à ExtJS 3 et 4 où ils ont réussi à implémenter assez bien les espaces de noms.
- ajouté après -1
Mon point ici était, il est possible de cacher toutes ces «circonvolutions» et d'avoir toujours un code assez convivial comme ceci:
la source