-
Notifications
You must be signed in to change notification settings - Fork 14
/
index_es-ar.html
922 lines (813 loc) · 64.8 KB
/
index_es-ar.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>
jQuery vs MooTools: Eligiendo entre dos Excelentes Frameworks de JavaScript
</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="Shortcut Icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="css/blueprint/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/blueprint/print.css" type="text/css" media="print">
<!--[if IE]><link rel="stylesheet" href="css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->
<link rel="stylesheet" href="css/blueprint/src/typography.css" type="text/css" media="screen" title="no title" charset="utf-8">
<style>
body {
font-size: 100%;
color: #444;
background: #fff;
font-family: "Georgia", Arial, Helvetica, sans-serif;
}
h1, h2, h3, h4 {
color: #626262;
}
h1 {
text-align: center;
margin: 20px !important;
font-size: 90px;
padding: 0 !important;
padding:0 0 10px;
}
div.caption {
font-size: 14px;
text-align: right;
margin: auto;
width: 800px;
position: relative;
top: -25px;
background-color: none;
}
a, a.visited {
color: #004d9b;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
p.footnote {
font-size: 12px;
text-align:right;
margin-top: 0px;
position: relative;
top: -8px !important;
top: 0px;
}
p.about {
font-size: 12px;
}
tr td {
border-bottom: 1px solid #999;
vertical-align: top;
}
tr th {
background: #999;
color: #fff;
}
.dsq-item-cp {
display: none;
}
div.trans {
font-size: 10px;
}
ul#dsq-comments {
max-height:800px !important;
overflow:auto !important;
padding:0 10px 0 0 !important;
}
</style>
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("mootools", "1.2.2");
</script>
<script src="js/Lighter/Ligher.uncompressed.js" type="text/javascript" charset="utf-8"></script>
<script>
window.addEvent('domready', function(){
var toc = $$('ul a');
$$('a:not(.stbutton)').each(function(a) {
if (toc.contains(a)) return;
a.set('target', '_blank');
});
if (Browser.Engine.trident) return;
// Highlight all "pre" elements in a document.
$$('pre').light({
altLines: 'hover',
indent: 2,
mode: 'pre',
path: 'js/Lighter/'
});
});
</script>
</head>
<body>
<div class="container">
<h1 class="span-24 last">jQuery vs MooTools</h1>
<div class="caption">
May, 2009 - <a href="http://www.clientcide.com" target="_blank">Aaron Newton of Clientcide</a>
<div class="trans">
Also available in
<a href="/index_pt-br.html">Portuguese (Brazil)</a>, <a href="/index_cn.html">Chinese</a>, <a href="index_fa.html">Farsi (Persian)</a>, <a href="/index.html">English</a>, <a href="/index_ja.html">Japanese</a>, and <a href="/index_it.html">Italian</a>. | <a href="http://wiki.github.com/anutron/jquery-vs-mootools">How to submit a translation</a>.
</div>
</div>
<p>
La mayoría de la gente que comienza con JavaScript en estos días se encuentra con la desafiante tarea de la elección de la biblioteca a usar, o al menos cual aprender primero. Si estas trabajando para una empresa, probablemente ellos ya han elegido un framework por tí, siendo este caso algo que se puede debatir. Si esta es la situación y ellos eligieron <a href="http://www.mootools.net">MooTools</a> y tu usas normalmente<a href="http://www.jquery.com">jQuery</a>, este artículo te puede ser aúnde utilidad.
</p>
<p>
<a href="http://twitter.com/joshink/statuses/1671986611">Cada</a> <a href="http://twitter.com/jezusisstoer/statuses/1642244246">día</a> <a href="http://twitter.com/digitalcampaign/statuses/1622094648">en</a> <a href="http://twitter.com/jesswma/statuses/1605733380">twitter</a> veo numerosos posts que caen en la pregutna "MooTools o jQuery?" Este artículo te ayudará a t tomar esa decisión.
</p>
<h3>Sobre el Autor</h3>
<p>
Soy un programador de MooTools. Trabajo en el framework de MooTools. Escribo sobre MooTools. Yo escribí<a href="http://www.mootorial.com">el principal tutorial online</a> y <a href="http://www.amazon.com/gp/product/1430209836?ie=UTF8&tag=clientside-20&link_code=as3&camp=211189&creative=373489&creativeASIN=1430209836">el libro sobre MooTools</a>. Obviamente, tengo una perspectiva que es algo tendenciosa. Aclarare también que no uso jQuery muy a menudo. Si eres un programador de jQuery y ves algo que yo he presentado mal aquí, por favor, contáctame y ayúdame a corregir el incidente. Mi objetivo aquí es ofrecer ayuda y ser conciso para los demás - no intento vender un framework sobre otro.
</p>
<h3>Sobre el tradutor</h3>
<p>Usuario de MooTools, jQuery y de <a href="http://www.workingwithrails.com/person/7271-pedro-visintin">Ruby On Rails</a>. Utilizo Clientcide normalmente y mi framework por elección de momento es MooTools.
<h3>Propósito</h3>
<p>
Ayudarte a hacer una elección entre estos dos frameworks me implica mostrarte en qué y cómo difieren los mismos. Comenzaré diciendo que <b>ambos son elecciones excelentes</b>. No puedes hacer una elección incorrecta en estas opciones. Ambos frameworks tienen sus fortalezas y debilidades, pero, en general ambos son excelentes opciones. Hay otros frameworks que merecen ser evaluados también. <a href="http://www.dojotoolkit.org/">Dojo</a>, <a href="http://www.prototypejs.org/">Prototype</a>, <a href="http://developer.yahoo.com/yui/">YUI</a>, <a href="http://extjs.com/">Ext</a> y otros son todos excelentes opciones. Cual elijas tiene más relación con tu propio estilo y cual es el problema a resolver. El objetivo de este artículo es enfocarnos en MooTools y jQuery, viendo el incremento de la consideración de estos dos frameworks por la gente. Finalmente, no estoy tratando de convencer a nadie de cambiar de un framework al otro. Hay cosas interesantes de estos dos frameworks de las cuales puedes aprender. Puedes leer un poco más sobre este artículo y porqué lo escríbí en <a href="http://www.clientcide.com/3rd-party-libraries/jquery-vs-mootools-mootools-vs-jquery/">mi entrada en el blog de Clientcide donde lo he anunciado</a>.
</p>
<h3>Contenidos</h3>
<ul>
<li><a href="#mottos">Los Definiciones lo dicen todo</a></li>
<li><a href="#learning">La Curva de Aprendizaje y La Comunidad</a></li>
<li><a href="#javascript">Para qué es bueno JavaScript</a></li>
<ul style="margin-bottom: 0px">
<li><a href="#dom">Más que solo el DOM</a></li>
<li><a href="#inheritance">Herencia con JavaScript</a></li>
<li><a href="#self">Auto Referencia</a></li>
</ul>
</li>
<li><a href="#jsfun">MooTools Hace JavaScript en sí Más Divertido</a></li>
<li><a href="#domfun">jQuery Hace el DOM Más Divertido</a></li>
<li><a href="#cando">Cualquier cosa que hagas yo lo puedo hacer mejor</a></li>
<li><a href="#yourway">MooTools te permite tenerlo a tu manera</a></li>
<li><a href="#chaining">Encadenado (Chaining) como un patrón de diseño</a></li>
<li><a href="#reuse">Reusando código con jQuery</a></li>
<li><a href="#classes">Reusando código con MooTools</a>
<ul>
<li><a href="#mooinheritance">MooTools y Herencia</a></li>
<li><a href="#extension">Extendiendo e Implementando Clases</a></li>
</ul>
</li>
<li><a href="#conclusion">Tiempo de Decisión</a></li>
<li><a href="#discussion">Discusión</a></li>
</ul>
<h2>Las Estadísticas</h2>
<table>
<tr>
<th></th>
<th>jQuery Core</th>
<th>MooTools Core</th>
</tr>
<tr>
<td>Tamaño de la biblioteca</td>
<td>55.9K</td>
<td>64.3K</td>
</tr>
<tr>
<th colspan="3">Prestaciones</th>
</tr>
<tr>
<td>Licencia</td>
<td><a href="http://en.wikipedia.org/wiki/MIT_License" title="MIT License">MIT</a> & <a href="http://en.wikipedia.org/wiki/GPL" title="GPL">GPL</a></td>
<td><a href="http://en.wikipedia.org/wiki/MIT_License" title="MIT License">MIT</a></td>
</tr>
<tr>
<td>Utilidades del DOM</td>
<td>sí</td>
<td>sí</td>
</tr>
<tr>
<td>Animación</td>
<td>sí</td>
<td>sí</td>
</tr>
<tr>
<td>Manejo de Eventos</td>
<td>sí</td>
<td>sí</td>
</tr>
<tr>
<td>Selectores CSS3</td>
<td>sí (un subset)</td>
<td>sí (un subset)</td>
</tr>
<tr>
<td>Ajax</td>
<td>sí</td>
<td>sí</td>
</tr>
<tr>
<td>Extensiones Natovas (excluyendo Element)</td>
<td>una docena aprox. para Array, Object, y String</td>
<td>como seis docenas, para Array, Object, String, Function, y Number</td>
</tr>
<tr>
<td>Herencia</td>
<td>No soportada directamente con jQuery</td>
<td>Provista con el constructor<em><a href="http://mootools.net/docs/core/Class/Class">Class</a></em></td>
</tr>
<tr>
<th colspan="3">Otras Consideraciones</th>
</tr>
<tr>
<td>plug-ins</td>
<td>Cientos de plug-ins no oficiales en un directorio en <a href="http://plugins.jquery.com/">plugins.jquery.com</a></td>
<td>Apenas 4 docenas de plug-ins oficiales disponibles en <a href="http://mootools.net/more">mootools.net/more</a>. Repositorio de plugins no oficial en <a href="http://mootools.net/plugins">mootools.net/plugins</a>.</td>
</tr>
<tr>
<td>Biblioteca de UI Oficial</td>
<td>sí</td>
<td>no</td>
</tr>
</table>
<p class="footnote">
Información basada en datos obtenidos de<a href="http://jquery.com">jquery.com</a>, <a href="http://mootools.net">mootools.net</a>, y <a href="http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks">wikipedia.com</a>.
</p>
<a name="mottos"></a>
<h2>Los Principios lo Dicen Todo</h2>
<p>
Si tu vas al sitio de jQuery, ésto es lo que dice en el comienzo de la página:
</p>
<blockquote>jQuery es una Biblioteca de JavaScript rápida y concisa que simplifica el recorrido, manejo de eventos, animación, y interacciones Ajax en el documento HTML para un rápido desarrollo web. jQuery está diseñado para cambiar la manera que tu escribes JavaScript.</blockquote>
<p>
...y si tu vas a MooTools, esto es lo que vas a encontrar:
</p>
<blockquote>MooTools es un compacto, modular, Object-Oriented JavaScript framework diseñado para el programador JavaScript intermedio a avanzado. Este permite escribir un código potente, flexible, y cross-browser con su elegante, bien documentada y coherente API. </blockquote>
<p>
Yo pienso que esto realmente lo resume. Si tu me preguntas (y estás leyendo esto, por lo que asumiré que lo estás haciendo), la pregunta no es sobre cual framework es mejor o peor. La pregunta es, cuales de estas cosas tu quieres hacer? Estos dos frameworks no están tratando de hacer las mismas cosas. Ellos se sobreponen en la funcionalidad que proveen, pero no están tratando de hacer las mismas cosas.
</p>
<p>
La descripción de jQuery's de si mismo habla sobre HTML, eventos, animaciones, Ajax, y desarrollo web. MooTools habla sobre orientación a objetos y sobre escribir codigo potente y flexible. jQuery aspira a "cambiar la forma que tu escribes JavaScript" mientras que MooTools está diseñado para el programador JavaScript intermedio y avanzado.
</p>
<p>
Parte de esta consideración es la noción de un <em>framework</em> vs un <em>toolkit</em>. MooTools es un <em>framework</em> que intenta implementar JavaScript <em>como deberia ser</em> (de acuerdo a los autores de MooTools). El objetivo es implementar un API que se percibe como JavaScript y mejora todo; no solo el DOM. jQuery es un <em>toolkit</em> que te brinda una colección de métodos de fácil uso en un sistema autocontenido y diseñado para hacer el DOM en si mismo más amigable. Sucede que la mayoría se enfoca en el DOM cuando escribe JavaScript, entonces en muchos casos, jQuery es todo lo que necesitas.
</p>
<p>
La mayor parte del código cuando escibes usando MooTools se sigue percibiendo como JavaScript. Si no estås interesado en JavaScript como un lenguaje, aprender MooTools se convertirá en una tarea pesada y no algo placentero. Si estás interesado en JavaScript y lo que lo hace interesante, poderoso, y expresivo, entonces, personalmente, yo pienso que MooTools es la mejor opción.
</p>
<a name="learning"></a>
<h2>La Curva de Aprendizaje y La Comunidad</h2>
<p>
Primero, jQuery es, por lejos, más facil de aprender. Tiene casi un estilo coloquial que uno casi no siente que está programando. Si todo lo que quieres es algo funcionando rápido sin aprender JavaScript, jQuery es probablemente una mejor elección para ti. Esto no significa que MooTools no te puede ayudar a completar las mismas tareas, pero debo admitir que MooTools puede ser un poco mas dificil de acostumbrarse si eres nuevo en JavaScript y también encontrarás muchos más recursos para aprender jQuery - más de los que hay para MooTools al menos.
</p>
<p>
Si comparas la comunidad jQuery (<a href="http://docs.jquery.com/Discussion">ver la página de "Discussion" en jQuery</a>) y la de la comunidad MooTools (<a href="irc://irc.freenode.net/#mootools">irc</a>, <a href="http://groups.google.com/group/mootools-users">lista de correo</a>, y <a href="http://mooforum.net/">foro no oficial</a>) descubrirás rápidamente dos cosas: 1) la comunidad dejQuery community es <i>por lejos</i> más grande (Yo atribuyo esto mayormente al punto que hice referencia anteriormente sobre cuan fácil es de aprender, pero también porque...) y 2) ellos son más activos promocionando la biblioteca. Si mides jQuery y MooTools en métricas como el número de gente usándolo, el número de consultas hechas en google, el número de libros vendidos, etc, verás a jQuery adelente por un gran margen.
</p>
<p>
Para decirte porqué debes considerar MooTools primero necesito hablar un poco sobre lo que ambos frameworks hacen. En última instancia el framework que elijas irá dependiendo de qué quieres realizar y como te gusta programar (y puede ser también <i>si</i> te gusta programar, al menos en JavaScript)
</p>
<a name="javascript"></a>
<h2>Para qué es bueno JavaScript</h2>
<p>
Parte de hacer esta eleccion es preguntar qué es lo que quieres hacer con JavaScript. Consideremos JavaScript básico. Sin ningun framework; solo JS. JavaScript te brinda objetos nativos como <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/String">Strings</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Number">Numbers</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function">Functions</a>, <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array">Arrays</a>, <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Date">Dates</a>, <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp">Regular Expressions</a>, y más. JavaScript también te brinda un modelo de herencia - una especie de modelo esotérico llamado <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance">prototypal inheritance</a> (de lo cual voy a profundizar más adelante). Estos bloques de construcción y el concepto de herencia son el pan y la manteca de cualquier lenguaje de programación y nada tienen que ver con los browsers o la web o CSS o HTML. Puedes escribir cualquier cosa que quieras en JavaScript. Ta-te-ti, ajedrez, edición de fotos, un web server, cualquier cosa. Sucede que el 99% de todo el JavaScript que anda por ahí se ejecuta en browsers y eso es como lo pensamos que es. El lenguaje de programación para los browsers.
</p>
<p>
Entendiendo que el browser, el DOM, es solo donde acostumbramos a usar JS la mayoria del tiempo pero saber que JS es actualmente un muy robusto y expresivo lenguaje de programación, te ayudará a entender la diferencia entre MooTools y Jquery.
</p>
<a name="dom"></a>
<h3>Mas que solo el DOM</h3>
<p>
Si piensas que las tareas a realizar en JavaScript estrictamente en términos de "obtener cosas en la página y hacer cosas con eso" entonces jQuery es probablemente la mejor opcion. Este se excede ofreciendo un sistema muy expresivo para describir comportamiento en la página en una manera que hace sentir muchas veces que uno no está programando. Tu puedes aun usar el resto de JavaScript para hacer lo que quieres hace, pero si estas enfocado en el DOM - cambiando propiedades de CSS, animando cosas, obteniendo contenido via AJAX, etc - la mayoría de lo que finalices escribiendo será cubierto por jQuery, y lo que no se asemejará al viejo puro JavaScript. jQuery provee algunos métodos que no aplican al DOM; por ejemplo, jQuery provee un mecanismo para iterar sobre arrays - <i><a href="http://docs.jquery.com/Utilities/jQuery.each">$.each(array, fn)</a></i> - o, por ejemplo, ofrece un método trim para strings - <i><a href="http://docs.jquery.com/Utilities/jQuery.trim">$.trim(str)</a></i>. Pero no hay una gran cantidad de estos métodos utilitarios, lo cual está bien porque, para la mayor parte, si tu estas obteniendo cosas del DOM, iterando sobre el, y alterándolo de alguna manera (agregando html, cambiando estilos, agregando eventos y listeners para click y mouseover, etc) no necesitaras mucho más que esto.
</p>
<p>
Pero si pensas en el alcance de JavaScript en su espectro completo, podes ver que Jquery no hace foco en las cosas fuera del DOM. Esta es una de las razones porqué es tan sencillo de aprender, pero esto también limita la forma en que te ayuda a escribir JavaScript. Este solo no esta tratando de ser ninguna otra cosa que un sistema sólido de programación <i>para el DOM</i>. No provee herencia ni proevee las utilidades básicas para todos los tipos nativos del lenguaje JavaScript, <i>pero no necesita hacerlo</i>. Si quieres meterte en el manejo de strings, fechas, expresiones regulares, arrays y funciones, <i>tu puedes</i>. No es el trabajo de jQuery ayudarte a hacerlo. JavaScript como lenguaje está ahi a tus pies. jQuery hace del DOM su cancha de juego, pero el resto de JavaScript no está en su alcance.
</p>
<p>
Aquí es donde MooTools es ampliamente diferente. En vez de enfocarse exclusivamente en el DOM (más exactamente, como veremos en breve, este ofrece toda la funcionalidad que jQuery tiene pero lo alcanza de una muy diferente manera), MooTools toma dentro de su alcance el lenguaje completo. Si jQuery hace del DOM su cancha de juego, MooTools intenta hacer a JavaScript su cancha de juego, y esa es una de las razones por la cuales es mas dificil de aprender.
</p>
<a name="inheritance"></a>
<h3>Herencia con JavaScript</h3>
<p>
Hay algunas cosas fascinantes sogre el lenguaje de programación JavaScript. Para los que empiezan, este es un <a href="http://en.wikipedia.org/wiki/Functional_programming">lenguaje funcional</a>, lo que significa que maneja las funciones como los objetos de mayor orden que pueden ser pasados a través de variables como cualquier otro objeto - strings o números por ejemplo. Está diseñado con este concepto en mente y muchos de los métodos y patrones en el trabajan mejor cuando escribes codigo de esa manera. Esta es la diferencia entre:
</p>
<pre class="js">for (var i = 0; i < myArray.length; i++) { /* hace algo */ }</pre>
<p>
and
</p>
<pre class="js">myArray.forEach(function(item, index) { /* hace algo */ });</pre>
<p>
JavaScript tiene un <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance">modelo de herencia</a> que no es particularmente único pero es bastante poco común en lenguajes de programación. En vez de clases que son definidas y pueden tener subclases éste pasa los comportamientos a través de <i><a href="http://en.wikipedia.org/wiki/Prototype-based_programming">herencia prototipada (prototypal inheritance)</a></i>. Esto significa que los objetos heredan directamente de otros objetos. Si referencias una propiedad de un objeto que hereda de otro objeto, el lenguaje inspecciona el objeto hijo por esa propiedad y, si no la encuentra, busca a ella en el padre. De esta manera es como trabaja un array. Cuando tipeas:
</p>
<pre class="js">[1,2,3].forEach(function(item) { alert(item) }); //esto hace alert 1 despues 2 despues 3</pre>
<p>
el método "<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Objects:Array:forEach">forEach</a>" no es una propiedad del array que declaraste (<em>[1,2,3]</em>), este es una propiedad del prototipo para todos los Arrays. Cuando referencias este método el lenguaje busca un método llamado <em>forEach</em> en tu array, y, si no lo encuentra, busca entonces en el prototipo de todos los arrays. Esto significa que el método <em>forEach</em> no está en memoria por cada array existente; éste está solo en la memoria del prototipo de arrays. Esto es increiblemente eficiente y bastante potente. (Nota: MooTools hace un alias de el metodo <em>forEach</em> llamándolo <em>each</em>)
</p>
<a name="self"></a>
<h3>Autoreferencia</h3>
<p>
Javascript tiene una palabra especial: "this". Esto es dificil para mi definir en forma resumida de que se trata este "this", por defecto, "this" es el objeto del cual se asocia el método corriente. Este permite a los objetos referise a si mismos, ya que de otro modo no tendrían la forma para hacerlo. Esto se vuelve importante cuando creas objetos hijos y tienes numerosas instancias de ese objeto; de qué otra manera el método de un objeto podria referise a sí mismo? Cuando la copia actual del método existe en el objeto padre, no en el hijo, la palabra "this" permite a estas instancias referirse a su propio estado. (<a href="http://www.quirksmode.org/js/this.html">aquí hay una descripcion mucho más completa sobre la palabra "this"</a>, y <a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Operators/Special_Operators/This_Operator">otra de Mozilla</a>.)
</p>
<p>
La palabra "this" permite a los objetos que heredan de otros objetos referirse a si mismos, pero hay veces donde quieres que se referencie a algo mas a través de "this". Esto es llamado <a href="http://alternateidea.com/blog/articles/2007/7/18/javascript-scope-and-binding">binding</a>, en donde especificas un "this" <i>different</i> para un método. El método "each" en un Array te permite especificar el objeto que será retornado cuando utilices "this" como segundo argumento. Aquí hay un ejemplo de donde deseamos usar un "this" diferente:
</p>
<pre class="js">var ninja = {
weapons: ['katana', 'throwing stars', 'exploding palm technique'],
log: function(message) {
console.log(message);
},
logInventory: function() {
this.weapons.each(function(weapon) {
//queremos que "this" esté apuntando a ninja...
this.log('this ninja can kill with its ' + weapon);
}, this); //entonces pasamos "this" (que es ninja) al método Array.each
}
};
ninja.logInventory();
//this ninja can kill with its katana
//this ninja can kill with its throwing stars
//this ninja can kill with its exploding palm technique</pre>
<p>
En el ejemplo anterior, nosotros enlazamos o asociamos (bound) ninja (el cual es "this" dentro de el método <em>logInventory</em>) al método que pasamos al array de esta manera podremos hacer referencia a la propiedad de log de ninja. Si no hicieramos esto "this" será <em>window</em>.
</p>
<p>
Estos son solo algunos ejemplos del poder y expresividad que JavaScript tiene para ofrecer - herencia, autoreferencia y enlace o asociación, y eficientes propiedades de prototipos. Las malas noticias es que el viejo JavaScript básico, no hace accessibles ni útiles estas poderosas cosas, y aquí es donde MooTools <i>comienza</i>. MooTools hace que estos tipos de patrones sean fáciles y porqué no placenteros de usar. Terminarás escribiendo código más abstracto, y en el largo plazo, esto es algo bueno - algo potente. Aprendiendo como estos patrones son valiosos y como usar ellos apropiadamente lleva esfuerzo, pero el lado bueno es que el código que escribes es altamente reusable y mucho más facil de mantener. Voy a hablar de estas dos cosas en un poco mas de un minuto.
</p>
<a name="jsfun"></a>
<h2>MooTools hace JavaScript en sí Más Divertido</h2>
<p>
MooTools se enfoca en hacer la API de JavaScript en sí más estable y coherente, está menos enfocado en brindarte una interfáz que "cambia la manera que escribis JavaScript" y más en hacer a JavaScript como un todo menos frustrante; MooTools es una extensión del lenguaje JavaScript. MooTools intenta hacer a JavaScript de la forma que debería ser. Una porción significante de la biblioteca principal esta dedicada mejorar Function, String, Array, Number, Element y otros prototipos. La otra gran cosa es que ofrece una función llamada <em><a href="http://mootools.net/docs/core/Class/Class">Class</a></em>.
</p>
<p>
Ahora, <em>Class</em> se ve para muchas personas como un intento de recrear una manera más clasica del modelo de herencia que uno podría encontrar en Java o C++, pero ese <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages">no es el caso</a>. Lo que <em>Class</em> realmente hace es hacer el modelo de herencia prototipada de JavaScript más sencillo para ti y para mi de acceder y tomar ventaja de ello. Notar qeu estos conceptos nos son únicos a MooTools (otros frameworks ofrecen similar funcionalidad), pero estos dos conceptos no estan presentes en jQuery. jQuery no ofree un sistema de herencia ni ofrece ninguna mejora a los objetos nativos (Funciton, String, etc). Esto no es una deficiencia de jQuery ya que los autores de jQuery podrían fácilmente ofrecer estas cosas. En cambio, ellos han diseñado un toolkit con una meta diferente con otra idea en la cabeza. Donde MooTools intenta hacer JavaScript mas divertido, jQuery intenta hacer el DOM más divertido y los diseñadores han elegido limitar su alcance para esa taréa.
</p>
<a name="domfun"></a>
<h2>jQuery Hace el DOM Más Divertido</h2>
<p>
Y esto es por qué jQuery es más accesible. El no te pide que aprendas JavaScript al derecho y al revés. El no te empuja dentro de las profundidades de herencia prototipada, enlazado, "this" y prototipos nativos. Cuando comienzas con jQuery en este <a href="http://docs.jquery.com/Tutorials:How_jQuery_Works">tutorial oficial</a>,
éste es el primer código ejemplo de jQuery con que te vas a encontrar:
</p>
<pre class="js">window.onload = function() {
alert("welcome");
}</pre>
<p>y aquí está el tercero: </p>
<pre class="js">$(document).ready(function() {
$("a").click(function(event) {
alert("Thanks for visiting!");
});
});</pre>
<p>
Si lees <a href="http://www.amazon.com/gp/product/1430209836?ie=UTF8&tag=clientside-20&link_code=as3&camp=211189&creative=373489&creativeASIN=1430209836">el libro de MooTools</a> o el <a href="http://www.mootorial.com/wiki">tutorial de MooTools </a> (ambos escritos por mi) ellos comienzan en un lugar muy diferente. Mientras puedes saltar adelante y rápidamente aprender los efectos y el DOM, si quieres aprender MooTools, tendras que empezar con cosas como <em>Class</em>, y, debo admitir: si sos nuevo en programacion, o simplemente quieres algo funcionando en tu sitio sin tener que aprender todo de JavaScript, jQuery te parecerá mucho más amigable.
</p>
<p>
Del otro lado, si quieres aprender JavaScript, MooTools es una excelente manera de hacerlo. Implementa un monton de cosas que JavaScript tendrá (muchos de los métodos en Natives son simplemente los de la especificación <a href="https://developer.mozilla.org/En/New_in_JavaScript_1.8">JavaScript 1.8</a> y posteriores). Si estas acostumbrado a programar, especialmente de ambas maneras, orientado a objetos y programación funcional, MooTools tiene un montón de patrones de diseño que son muy interesantes y expresivos.
</p>
<a name="cando"></a>
<h2>Cualquier cosa que hagas Yo lo puedo hacer mejor</h2>
<p>
Si miras las cosas que jQuery puede hacer, siempre hay una contraparte en MooTools. Si miras las cosas que MooTools puede hacer, no siempre encontraras su contraparte en jQuery debido a que jQuery se enfoca en el DOM. MooTools tiene tiene una funcionalidad más amplia que jQuery, pero no hay nada en jQuery que evite que las hagas. Por ejemplo, jQuery no viene con ninguna clase de sistema de herencia, pero eso está bien. Tu podrias, si quieres, usar MooTools <em>Class</em> en conjunto con jQuery si lo deseas (o escribir tu propia implementación). Hay incluso <a href="http://code.google.com/p/jquery-inheritance/updates/list">un plug-in de herencia para jQuery</a> (No lo he usado, pero asumo que ofrece el mismo tipo de funcionalidad).
</p>
<p>Si miramos al ejemplo anterior de jQuery:</p>
<pre class="js">$(document).ready(function() {
$("a").click(function(event) {
alert("Thanks for visiting!");
});
});</pre>
<p>
y queremos traducirlo a MooTools, tendríamos que hacer:
</p>
<pre class="js">window.addEvent('domready', function() {
$$('a').addEvent('click', function(event) {
alert('Thanks for visiting!');
});
});</pre>
<p>
Muy similares no?
</p>
<p>
Este es un ejemplo de jQuery un poco más complejo:
</p>
<pre class="js">$(document).ready(function() {
$("#orderedlist li:last").hover(function() {
$(this).addClass("green");
},
function() {
$(this).removeClass("green");
});
});</pre>
<p>
y en MooTools:
</p>
<pre class="js">window.addEvent('domready',function() {
$$('#orderedlist li:last-child').addEvents({
mouseenter: function() {
this.addClass('green');
},
mouseleave: function() {
this.removeClass('green');
}
});
});</pre>
<p>
De nuevo, muy similares. Debo mostrar que la versión de MooTools es más explícita, pero tambíen más verborrágica a causa de ello. Queda claro leyendo el código de MooTools que estamos agregando dos eventos - uno para cuando el mouse entra y otro cuando el mouse sale, mientras que la versión de jQuery es más concisa; su método <em><a href="http://docs.jquery.com/Events/hover">hover</a></em> acepta dis métodos - el primero para cuando el mouse entra y otro para cuando sale. Me gusta mas, personalmente, el hecho de que el código de MooTools es más legible pero esa es una observación muy subjetiva.
</p>
<p>
Voy a decir que jQuery a veces puede volverse demasiado esotérico para mi gusto. Los métodos no siempre me transmiten sobre qué hacen cuando los miro y lo encuentro dificil para recorrerlos. Esto es algo injusto creo, porque yo estoy intimamente relacionado con MooTools, por lo tanto leer MooTools es fácil para mi. Pero una de las cosas que aprecio de MooTools es cómo casi todos los métodos y clases realmente definen lo que son. Los métodos son casi siempre verbos y dejan muy poca duda sobre lo que hacen. Cada lenguaje de programación requiere de la lectura de la referencia y de la sintaxis cuando escribes código - No estoy diciendo eso. Yo solo digo que encuentro el API de MooTools más coherente y consistente.
</p>
<a name="yourway"></a>
<h2>MooTools te permite tenerlo a tu manera</h2>
<p>Pero, que pasa si te gusta la sintaxis de jQuery? Una forma de ilustrar el poder de MooTools es mostrarte cuán fácil es cambiarlo para que quede como te gusta. Si queremos implementer el método <em>hover</em> de jQuery en MooTools, podemos hacerlo fácilmente así:</p>
<pre class="js">Element.implement({
hover : function(enter,leave){
return this.addEvents({ mouseenter : enter, mouseleave : leave });
}
});
//entonces tu puedes usarlo exactamente como la versión de jQuery:
$$('#orderlist li:last').hover(function(){
this.addClass('green');
},
function(){
this.removeClass('green');
});
</pre>
<p>De hecho, hay plug-ins de MooTools que justamente hacen eso; <a href="http://github.com/cheeaun/mooj/tree/master">ofreciendo la sintaxis de jQuery en MooTools</a>. Que MooTools esté enfocado en la extensibilidad significa que puedes implementar lo que quieras. Esto es algo que jQuery no puede hacer. MooTools puede emular jQuery si lo quieres, pero jQuery no puede emular MooTools. Si deseas escribir clases o extender prototipos nativos o hacer alguna de las otras cosas que MooTools puede, lo tendrás que escribir todo tú mismo.</p>
<a name="chaining"></a>
<h2>Encadenado (Chaining) como un patrón de diseño</h2>
<p>
Hagamos otro de estos. Aqui estan algunos ejemplos de jQuery (del tutorial de jQuery):
</p>
<pre class="js">$(document).ready(function() {
$('#faq').find('dd').hide().end().find('dt').click(function() {
$(this).next().slideToggle();
});
});</pre>
<p>
Este es un ejemplo de una sintaxis que personalmente no prefiero. Mirando al codigo anterior estoy fuertemente presionado a asegurarme de que es lo que está haciendo. Más notablemente estoy curioso sobre que es lo que hace <i>.end</i> y como despues hace <i>.find</i>, el cual está contiguo, relacionado a lo que hace <i>.end</i>? Ahora bien, mirando la referencia de jQuery nos deja bienl claro que es lo que .end hace (éste vuelve al valor del selector original, en este caso #faq). Pero esto se ve muy extraño para mí. Cuando trabajo con jQuery, a menudo, me encuentro inseguro sobre lo que un método irá a devolverme. Obviamente esto no le preocupa a nadie mas siendo que jQuery tiene un monton de gente usándolo felizmente, por lo tanto lo marcare nuevamente como una preferencia personal.
</p>
<p>
Miramos la lógica anterior desde MooTools:
</p>
<pre class="js">window.addEvent('domready', function() {
var faq = $('faq');
faq.getElements('dd').hide();
faq.getElements('dt').addEvent('click', function() {
this.getNext().slide('toggle');
});
});
</pre>
<p>
Nuevamente, el código de MooTools es un poco más verborrágico, pero también, más explícito. Nota también que el patrón de diseño aquí es almacienar la referencia a #faq en una variable, donde jQuery usa el método <i>.end</i> para devolverla. Quiero notar que es posible escribir código con mucho encadenamiento en MooTools. Por ejemplo:
</p>
<pre class="js">item.getElements('input[type=checkbox]')
.filter(function(box) {
return box.checked != checked;
})
.set('checked', checked)
.getParent()[(checked) ? 'addClass' : 'removeClass']('checked')
.fireEvent((checked) ? 'check' : 'uncheck');</pre>
<p>
Pero realmente, escribir codigo como este - un montón de lógica en una sentencia de domready - con cualquier framework, yo sostengo, que en sí misma es una mala práctica. Es por lejos mucho mejor encapsular la lógica en partes reutilizables.
</p>
<a name="reuse"></a>
<h2>Reusando código con jQuery</h2>
<p>
Es muy tentador cuando estas trabajando en un proyecto web para escribir código de esta manera. Solo agregas un poco de lógica en la página que selecciona los elementos del DOM y "los prepara" ocultando algunos, alterando otros, y agregando listeners para click o mouseover. Desarrollar código en esta manera es muy eficiente, y muy rápido. El problema con escribir toda tu lógica en las sentencias de domready es que terminarás con un montón de código que hace la misma cosa en diferentes lugares. Si tomamos el patron de FAQ anterior nosotros podemos aplicar esa lógica fácilmente en cualquier otra página con cualquier lista de términos y definiciones. Vamos a repetir la misma lógica cada vez que encontremos este patrón?
</p>
<p>
Una manera simple de hacerlo reusable es contener la lógica en una función y pasarla en argumentos. Aquí esta como debería verse en jQuery:
</p>
<pre class="js">function faq(container, terms, definitions) {
$(container).find(terms).hide().end().find(definitions).click(function() {
$(this).next().slideToggle();
});
};
$(document).ready(function() {
faq('#faq', 'dd', 'dt');
});</pre>
<p>
Esto es mucho mejor por dos razones realmente grandes e importantes:
</p>
<ol>
<li>
Si mañana necesitamso cambiar como estas listas trabajan (puede ser agregar una lógica de seguimiento de clicks de esa manera podemos medir en nuestros logs o puede que querramos obtener las definiciones via ajax) nosotros solo cambieremos nuestro método principal <i>faq</i> y en cualquier otro lugar donde se use estará actualizado. O también si hubiera una nueva versión de jQuery que cambia la forma en que las cosas funcionan, solo actualizamos nuestro único método en vez de docenas de copias por todos lados. Yo llamo a esto <em>keeping a small footprint in my application</em>. Manteniendo los puntos donde mi aplicación usa mi código mas genérico tan pequeña como sea posible, me hace mås fácil la corrección de errores, actualizar frameworks, agregar prestaciones, o alterar la funcionalidad.
</li>
<li>
La segunda razon es que esti es menos código. Reusando el mismo método una y otra vez, no me repito a mi mismo y esto es valioso en cualquier entorno de programación. Esto hace también que el código que mis visitantes tienen que bajar sea más pequeño.
</li>
</ol>
<p>
jQuery actualmente tiene un levemente refinado sistema para escribir "widgets" reusables como estos. En lugar de incitarte a escribirlo en funciones como el ejemplo anterior (que en realidad es bastante crudo) te incita a escribir <a href="http://docs.jquery.com/Plugins/Authoring">jQuery plug-ins</a>. Así es como esto se vería:
<pre class="js">jQuery.fn.faq = function(options) {
var settings = jQuery.extend({
terms: 'dt',
definitions: 'dd'
}, options);
//"this" is the current context; in this case, the elements we want to turn into faq layouts
$(this).find(settings.terms).hide().end().find(settings.definitions).click(function() {
$(this).next().slideToggle();
});
return this;
};</pre>
</p>
lo cual lo podemos usar de esta manera:
</p>
<pre class="js">$('#faq').faq();</pre>
<p>
Pero mirando el ejemplo anterior, no hay mucha diferencia entre declarar nuestra función <i>faq</i> de esta manera versus declararla como una función simple. Bueno, ella no esta en el namespace global, pero podríamos tenerla agregada facilmente a nuestro propio namespace. Asociandola con jQuery nosotros podemos anidarla con otros métodos jQuery. El otro beneficio es que el "this" dentro de nuestra función es el contexto corriente de lo que contiene el anidamiento jQuery en ese momento. Usando este patrón para plug-ins estamos en condiciones de hacer que nuestro plug-in se vea como parte de jQuery, pero por otro lado, nuestro plug-in es basicamente una simple función que toma el contexto actual de jQuery, hace cosas con eso, y después retorna el contexto para el siguiente item en el anidamiento o cadena (chain). No hay un monton de complejidad aqui, lo cual hace sencillo para cualquiera escribir plug-ins de jQuery - ya que son simplemente funciones.
</p>
<p>
Nota que es posible escribir plug-ins más complejos con jQuery con métodos y estado. Esta clase de patrón es soportado con el plug-in de jQuery llamado UI system y no usa el mismo mecanismo del plug-in básico (como nuestro ejemplo de faq). En cambio, puedes anexar un objeto con métodos y propiedades al objeto jQuery (por ejemplo <em>$.ui.tabs</em>). Hay un acceso directo para invocar este objeto (<em>$(selector).tabs()</em>) de manera que puedes continuar anidando como el plug-in de faq. Pero como este no retorna una referencia al objeto tabs creado para los items en tu selector, te ves forzado a llamar a ese selector nuevamente para llamar a los métodos que contiene. En vez de llamar <em>myTabInstance.add(url, label, index)</em> debes ejecutar el selector nuevamente y llamar tu función por nombre (como string): <em>$(selector).tabs('add', url, label, index);</em>. Esto significa que estas ejecutando tu selector dos veces (al menos que lo almacenes en alguna variable en algún lugar), y que nunca tienes una referencia al método "add" que tu podrías facilmente hacer cosas como bind o delay. Este artículo está enfocado en el core de MooTools y jQuery, y mientras UI system de jQuery provee esta funcionalidad, es algo que no viene por defecto.
</p>
<a name="classes"></a>
<h2>Reusando código con MooTools</h2>
<p>
En MooTools cuando quieres definir un patrón, tu puedes usar probablemente o una <em><a href="http://mootools.net/docs/core/Class/Class">Class</a></em> o implementar un método en un objeto nativo (en em>String</em>, por ejemplo).
</p>
<p>
En lugar de darte un casi completamente diferente lenguaje del estilo nativo de JavaScript, MooTools intenta caminar en el terreno entre definir su propia sintaxis y extender los patrones existentes en JavaScript. Uno de las maneras de hacer esto es extendiendo los prototipos de los objetos nativos en el lenguaje y en el DOM. Esto significa que si necesitas un método para remover los espacios de un string, MooTools te incita a agregar un método a String (nota que <em><a href="http://mootools.net/docs/core/Native/String#String:trim">String.trim</a></em> ya está implementado en MooTools; no necesitas agregarlo tu mismo):
</p>
<pre class="js">String.implement({
trim: function() {
return this.replace(/^\s+|\s+$/g, '');
}
});</pre>
<p>
Esto significa que simplemente puedes ejecutar <i>" no más espacios al final! ".trim()</i> y obtener <i>"no más espacios al final!"</i>. Alguien puede decir que implementar propiedades en los objetos nativos es inapropiado. Esta es la razón porque MooTools y <a href="http://www.prototypejs.org/">Prototype.js</a> no se llevan bien juntos - cualquier framework que manipula prototipos de nativos no puede llevarse bien con otro que hace lo mismo. Si yoi defino <i>String.prototype.foo()</i> y otra biblioteca en la misma página define lo mismo también, la que lo haga último ganará. De modo que, este es un problema similar al de global window namespace. Así es como funciona JavaScript. Esto es como a href="https://developer.mozilla.org/En/New_in_JavaScript_1.8">JavaScript 1.8</a> ha agregado muchas prestaciones. Las agrega a los prototipos.
</p>
<p>
Los programadores de MooTools incluyen un robusto framework que te facilita para extenderlo con tu propia funcionalidad con la intención de que la gente que incluya el framework en la pagina vaya a usarlo y no use algún otro framework. Actualmente pedir a los usuarios que descarguen dos frameworks sería un poco grosero. La única razón para incluir dos frameworks es porque deseas usar plug-ins de ambos, y en la mente de los autores de MooTools (me incluyo), si quieres un plug-in que no está disponible en el framework que elejiste, es más apropiado invertir tiempo portándolo a tu entorno que pedir que descarguen otro framework adicional.
</p>
<p>
Una vez que aprendes como funciona JavaScript y ves el poder de extender los objetos nativos, un nuevo nivel de programación se abre delante tuyo. Puedes escribir plug-ins que modifiquen Element o Date o Funcion. Mientras algunos pueden decir que agregar métodos a nativos de esta manera puede ser una clase de polución. Yo digo que esta es la manera que JavaScript fue pensado para ser usado. Es una cualidad de diseño del lenguaje. Agregando métodos a nativos te permite tener codigo conciso y compartimentado. jQuery hace esto también, pero limita las mejoras de prototipo al objeto jQuery.
</p>
<p>
Mientras puedes anidar facilmente varias llamadas a métodos en el objeto jQuery, en cualquier otro tipo de objeto tendrás que usar generics. Por ejemplo, en jQuery si quieres hacer trim a un string e iterar sobre cada línea, deberías escribir:
</p>
<pre class="js">$.each( $.trim( $('span.something').html() ).split("\n"), function(i, line){alert(line);});</pre>
<p>Pero como MooTools modifica los prototipos, tu puedes hacer esto:</p>
<pre class="js">$('span.something').get('html').trim().split("\n").each(function(line){alert(line);});</pre>
<p>
Hechando una mirada a esto pone extremadamente claro cuan potente es modificar prototipos. La anidación de elementos del DOM no es el unico lugar donde la anidación es util. MooTools te permite anidar métodos a cualquier objeto, incluyendo ejecutar un método en multiples elementos a la vez.
</p>
<p>
La clave aquí es que en el corazón del framework MooTools está la noción que está ahí para permitirte programar lo que quieras. Si hay una funcionalidad que no esta en el core, puedes extenederlo y agregarla tu mismo. El trabajo del core no es proveer todas las funcionalidades que cada uno quiere, sino proveer las herrramientas que te permiten escribir las cosas que desees. Una gran parte de ello es hacer la extensión de nativos más facil para ti, y obtener ventaja de la herencia prototipada. Puedes hacer estas cosas con JavaScript básico pero MooTools lo hace más fácil y placentero.
</p>
<a name="mooinheritance"></a>
<h3>MooTools y Herencia</h3>
<p>
A pesar de su nombre, la funcion de MooTools <em>Class</em> no es relamente una clase ni crea ellas. Ella tiene un patrón de diseño que puede hacerte acordar a las clases en un lenguaje de programación más tradicional, pero
lo que <em>Class</em> realmente hace tiene que ver con objetos y herencia prototipada. (Desafortunadadmente, usando palabras como "class" es lo más conveniente para describir estas cosas, de modo que para el propósito de éste artículo, cuando me refiera a "classes" me estoy refiriendo a funciones que retornan objetos - los que "instanciaré" - que heredan de prototipos.)
</p>
<p>
Para hacer una clase, debes pasarle un objeto al constructor <em>Class</em> de esta manera:
</p>
<pre class="js">var Human = new Class({
initialize: function(name, age) {
this.name = name;
this.age = age;
},
isAlive: true,
energy: 1,
eat: function() {
this.energy = this.energy + 1; //lo mismo que this.energy++
}
});</pre>
<p>
Tu le pasas a <em>Class</em> un objeto (en el ejemplo de arriba, le pasamos un objeto con miembros como "isAlive" y "eat") y este objeto se convierte en el prototipo de cada instancia de esa clase. Para crear una instancia, debes escribirlo de esta manera:
</p>
<pre class="js">var bob = new Human("bob", 20); //el nombre de bob es "bob" y el tiene 20 años.</pre>
<p>
Ahora tenemos una instancia de <em>Human</em>. <em>bob</em> tiene las propiedades de el objeto que definimos cuando nosotros creamos nuestra clase <em>Human</em>. Pero lo importante aquí es que <em>bob</em> tiene las propiedades a través de la herencia. Cuando referenciamos <i>bob.eat</i>, <i>bob</i> no tiene realmente esta propiedad. JavaScript mira en <i>bob</i> y el no tiene un método <i>eat</i>, por eso busca hacia arriba en la cadena de herencia y lo encuentra en el objeto que le pasamos cuando creamos la clase <em>Human</em>. Esto es válido también para <i>energy</i>. A primera vista esto se ve potencialmente malo; nosotros no queremos que todos los humanos que creemos obtengan energía cada vez que <i>bob</i> come (eats). Lo importante a reconocer es que la primera vez que asignamos un valor a la energía de <i>bob</i>(bob's energy), estamos asignando a su propio valor y no buscamos más en el prototipo por el. De modo que, la primera vez que llamamos al método eat de <i>bob</i>, el obtiene su propia definicion para <em>energy</em> (seteada en 2).
</p>
<pre class="js">bob.eat(); //bob.energy == 2</pre>
<p>
Notar que el nombre de <em>bob</em> y la edad son solo de el; estos son asignados a el cuando la clase es inicializada en el método <i>initialize</i>.
</p>
<p>
This whole pattern may seem a little odd to you, but the value here is that we can define functionality for a pattern and create instances of that pattern every time we need it. Each instance maintains its own state. So if we create another instance each one is independent of the other, but inherits from the same base pattern:
</p>
<pre class="js">var Alice = new Human();
//alice.energy == 1
//bob.energy == 2</pre>
<p>
Donde las cosas se ponen realmente interesantes es cuando queremos fundamentar este comportamiento.
</p>
<a name="extension"></a>
<h3>Extendiendo e Implementando Clases</h3>
<p>
Revisitemos nuestro plug-in <i>faq</i> de jQuery. Qué deberia suceder so queremos agregar más funcionalidad a ese plug-in. Que si queremos hacer una versión ajax que obtiene las respuestas a las preguntas de el server? Imaginemos que el plug-in <i>faq</i> fué hecho por alguna otra persona y queremos agregarle más cosas sin modificarlo de ninguna manera (no queremos hacer un fork).
</p>
<p>
Nuestras unicas opciones reales son, o duplicar la lógica completa del plug-in <em>faq</em>(recuerda que es solo una simple función), haciendo un fork escencialmente, o podemos invocarlo y agregarle más logica a el. Dadas las opciones, la última parece traernos menos problemas. Entonces esto debería verse algo así:
</p>
<pre class="js">jQuery.fn.ajaxFaq = function(options) {
var settings = jQuery.extend({
//algunas opciones especificas de ajax para obtener la información
url: '/getfaq.php'
definitions: 'dd'
}, options);
//"this" en el contexto actual; en este caso, el elemento que queremos transformarlo en el faq layout
$(this).find(settings.definitions).click(function() {
$(this).load(.....); //la lógica que obtiene el contenido
});
this.faq(); //la llamada a nuestro plug-in original
});</pre>
<p>
Esto tiene algunas cosas malas. Primero de todo, nuestra clase <em>faq</em> va a repetir nuestro selector para las definiciones, lo cual puede ser costoso; no hay forma de almacenar las definiciones obtenidas y pasarlas por segunda vez donde son requeridas. Secundariamente, no podemos agregar nuestra lógica ajax dentro de la propia lógica plug-in <em>faq</em> para mostrar la definición que obtuvimos via ajax. El plug-in original llamado <em>slideToggle</em> el cual expande la definición usando un efecto. Esto es problemático porque éste efecot va a finalizar antes que nuestro ajax se termine de cargar. No hay una solución real aquí al menos que dupliquemos completamente el plug-in <em>faq</em>.
</p>
<p>
Consideremos ahora nuestra clase <em>Human</em> en MooTools. Esta tiene propiedades como <em>isAlive</em> y <em>energy</em> y ademas tiene un método llamado <em>eat</em>. Qué pása si queremos hacer una nueva versión de <em>Human</em> que tenga propiedades adicionales? Con MooTools, extendemos la clase:</p>
<pre class="js">var Ninja = new Class({
Extends: Human,
initialize: function(name, age, side) {
this.side = side;
this.parent(name, age);
},
energy: 100,
attack: function(target) {
this.energy = this.energy - 5;
target.isAlive = false;
}
});</pre>
<p>
Puedes ver que hemos agregado un monton de funcionalidad en una subclase. Esta subclase tiene todas las propiedades que son únicas a <em>Ninjas</em>. <em>Ninjas</em> comienza con un valor inicial de <em>energy</em> de 100.
<em>Ninjas</em> obtienen un <em>side</em> . Ellos también obtienen un método <em>attack</em> que les permite matar a otros <em>Humans</em>, pero esto consume la energía de <em>Ninja</em>.
</p>
<pre class="js">var bob = new Human('Bob', 25);
var blackNinja = new Ninja('Nin Tendo', 'unknown', 'evil');
//blackNinja.isAlive = true
//blackNinja.name = 'Nin Tendo'
blackNinja.attack(bob);
//bob never had a chance</pre>
<p>
Alejandonos de esto un momento, hay algunas cosas interesantes a considerar aquí. Nota que tenemos un método <em>initialize</em> en la clase <em>Ninja</em>. Esto podría parecer que sobreescribe el método <em>initialize</em> en la clase <em>Human</em>, pero podemos seguir accediendo al mismo llamando a <em>this.parent</em>, pasando los argunmentos que la clase padre espera en el método <em>initialize</em>.
Más adelante, podemos controlar dónde sucede nuestra lógica; antes o despues de la llamada del método padre (this.parent). Podemos asignar nuevos valores a las propiedades (como el valor de <em>energy</em>) y podemos definir una nueva funcionalidad. Imagina si podriamos hacer esto en nuestro plug-in <em>faq</em> en jQuery. Podriamos cargar nuestra respuesta ajax y ENTONCES mostrar el valor con un efecto slide open.
</p>
<p>
MooTools tiene otro patron llamado Mixin. A diferencia de la relacion padre a hijo que es definida extendiendo una clase en una sublcase, puedes también definir clases que son mezcladas en otras clases para imbuir ellas con sus propiedades. Aqui un ejemplo:
</p>
<pre class="js">var Warrior = new Class({
energy: 100,
kills: 0,
attack: function(target) {
target.isAlive = false;
this.energy = this.energy - 5;
this.kills++;
}
});</pre>
<p>
Aquí hemos quebrado las cualidades que hacían a un <em>Ninja</em> diferente de un <em>Human</em> y pusimos esto en una clase. Esto nos permite reusar el codigo fuera de <em>Ninja</em>. Podríamos entonces imbuir nuestra clase <em>Ninja</em> con las cualidades de warrior así:
</p>
<pre class="js">var Ninja = new Class({
Extends: Human,
Implements: Warrior, //puede ser un array si deseas implementar más de uno
initialize: function(name, age, side) {
this.side = side;
this.parent(name, age);
}
});</pre>
<p>
<em>Ninja</em> continua funcionando como lo hice anteriormente, pero <em>Warrior</em> esta a nuestra disposición para ser reusado:
</p>
<pre class="js">var Samurai = new Class({
Extends: Human,
Implements: Warrior,
side: 'good'
});</pre>
<p>
Ahora tenemos una clase <em>Samurai</em> y una clase <em>Ninja</em>. Pero miremos cuan pequeño es el codigo para definir ambas clases <em>Ninja</em> y <em>Samurai</em>. Ambas son similares en que son humanos con cualidades de warrior, pero ellas son diferentes en que samurais son siempre, siempre buenos (good), mientras que los ninjas pueden cambiar sus lealtades. Invirtiendo el tiempo en escribir la clase <em>Human</em> y la clase <em>Warrior</em>, estaremos en condiciones de tener tres clases diferentes con ninguna repetición de codigo mientras mantiene un nivel de control muy granular sobre los métodos cuando son llamados y cómo se relacionan uno con otro. Cada instancia que creamos tiene su propio estado y el código en sí es muy legible.
</p>
<p>
Ahora que tienes un panorama de como las clases funcionan en MooTools, echémosle una mirada a nuestra clase <em>faq</em> que escribimos en jQuery y escribámosla en MooTools y luego extendámosla a Ajax como lo hicimos con jQuery.
</p>
<pre class="js">
var FAQ = new Class({
//Options es otra clase provista por MooTools
Implements: Options,
//these are the default options
options: {
terms: 'dt',
definitions: 'dd'
},
initialize: function(container, options) {
//guardamos una referencia a nuestro contenedor
this.container = $(container);
//setOptions es un método provisto por el mixin Options
//éste une (merge) las opciones que le pasamos con las opciones por defecto
this.setOptions(options);
//almacenamos los términos y definiciones
this.terms = this.container.getElements(this.options.terms);
this.definitions = this.container.getElements(this.options.definitions);
//llamamos a nuestro método attach
//separando esto en su propio método
//hace nuestra clase más fácil de extender
this.attach();
},
attach: function(){
//iteramos por los términos
this.terms.each(function(term, index) {
//agregamos el evento Click a cada uno
term.addEvent('click', function(){
//esto llama a nuestro método toggle para
//el index actual
this.toggle(index);
}, this);
}, this);
},
toggle: function(index){
//invierte la definicion abierta por la recibida en index
this.definitions[index].slide('toggle');
}
});
</pre>
<p>
Woah (Necesito un traductor especial para esta palabra ;-) ). Esto es un montón de código. Así y todo si elimino las líneas de comentarios quedan como dos docenas de líneas de código. Ya he ilustrado anteriormente que podríamos hacer este plug-in con la misma cantidad de código como la versión de jQuery. Entonces porqué éste es tanto mas largo? Bien, lo hemos hecho mucho más flexible. Para usasr la clase, simplemente llamamos el constructor, así:
</p>
<pre class="js">var myFAQ = new FAQ(myContainer);
//y ahora podemos llamar los métodos que contiene cuando querramos:
myFAQ.toggle(2); //invierte el 3er elemento
</pre>
<p>
Podemos acceder a los métodos y propiedades de la instancia. Pero que pasa con nuestra funcionalidad ajax? El problema con nuestra extensión ajax en nuestra versión jQuery era que no podíamos frenar la apertura de la definición hasta despues de la carga de la misma. No tenemos ese problema con nuestra versión de MooTools:
</p>
<pre class="js">FAQ.Ajax({
//esta clase hereda las propiedades de FAQ
Extends: FAQ,
//esta también obtiene una nueva opción sumada a las por defecto
//esta es para la url, lo que vamos a agregar al indice del término
//en realidad podemos hacer esto más robusto, pero para
//este ejemplo es suficiente
options: {
url: null;
},
//vamos a hacer caching de los resultados, de mode que si una seccion es
//abierta dos veces, no iremos al servidor por los datos nuevamente
indexesLoaded: [],
toggle: function(index){
//si ya hemos leído la definicion
if (this.indexesLoaded[index]) {
//solo llamamso la version previa de toggle
this.parent(index);
} else {
//cualquier otro caso, obtenemos los datos del server
new Request.HTML({
update: this.definitions[index],
url: this.options.url + index,
//cuando los datos estan cargados, expandimos la definición
onComplete: function(){
this.indexesLoaded[index] = true;
this.definitions[index].slide('toggle');
}.bind(this)
}).send();
}
}
});
</pre>
<p>
Ahora tenemos una versión de nuestra clase <em>FAQ</em> que nos permite obtener definiciones desde el servidor. Notar que ahora estamos en condiciones de integrar la nueva manera de no expandir la definicion hasta <em>después</em> que el contenido llegó del server (lo cual no hemos podido realizar con la versión de jQuery). También nota que nosotros realmente tenemos solamente que describir nueva funcionalidad (la ajax) y un poquito más. Esta extensibilidad hace te hace posible crear familias de plug-ins que ofrecen diferentes estilos de funcionalidades. Esto también significa que puedes usar el plug-in de alguien más y modificar solo el comportamiento que quieres que sea diferente si necesitas (sin realizar un fork). Esto ayuda a explicar porqué, para cualquier patron de diseño dado - un selector de fecha, una interfase con tabs, etc, que normalmente encuentras solo unos pocos plug-ins para MooTools. La mayoría de los plug-ins que obtienes o solucionan tu problema o, si no, simplemente puedes extenderlos para agregar las cosas que necesitas.
</p>
<p>
Como he ilustrado anteriormente, es posible escribir código complejo con widtets de jQuery con métodos y estados. La mayoría del codigo que escribes cuando estas haciendo esto es JavaScript básico cuando necesitas expresar lógica que no está relacionada al DOM. Pero el modelo jQuery no ofrece un sistema para extender estas instancias en subclases. Ni tampoco te ayuda con mixins que pueden ser reusados fácilmente. Finalmente, los plug-ins de jQuery están siempre asociados a elementos DOM. Si quieres escribir una clase que, devuelva, URLs procesadas, no hay ningun sistema stateful para ese tipo de cosas excepto que lo escribas tu mismo.
</p>
<a name="conclusion"></a>
<h2>Tiempo de decisión</h2>
<p>
jQuery se enfoca en expresividad, codificación fácil y rápido, y en el DOM mientras MooTools se enfoca en extensión, herencia, legibilidad, reuso, y mantenibilidad. Si tu pones estas dos cosas en la balanza, el lado de jQuery se traduce en algo que es fácil para empezar y se ven rápido los resultados pero (en mi experiencia) se puede convertir en código más dificil de mantener o reusar (pero realmente eso está de tu lado, no es un problema de jQuery), mientras el lado de MooTools toma más tiempo para aprender y requiere que escribas más código antes que puedas ver los resultados, pero luego es más reusable y mantenible.
</p>
<p>
El core de MooTools no contiene cada prestacione que puedes imaginar ni tampoco lo hace el core de jQuery. Ambos frameworks mantienen sus cores bastante limitados, dejandote a vos y a otros escribir plug-ins y extensiones. Su trabajo no es darte cada prestación que podrías querer sino darte las herramientas para que puedas implementar cualquier cosa que puedas imaginar. Este es el poder de JavaScript, y de los frameworks de JavaScript en general, y ambos frameworks sobresalen en esto. MooTools toma un acercamiento más holístico y te da un superset de las prestaciones de jQuery, pero jQuery se enfoca en ser una rápida API del DOM que no evita que uses la herencia nativa de los métodos de JavaScript o de usar un sistema de clases como MooTools si lo deseas.
</p>
<p>
Esto es porqúe yo digo que ambos frameworks son excelentes opciones. Mi esfuerzo aquí ha sido resaltar las diferencias de filosofías entre las dos lineas de codificación y resaltar sus ventajas y desventajas. Dudo que haya tenido éxito en mantener mi preferencia por MooTools en jaque, pero ojalá esto haya ayudado.
Sin hablar de que framework elijas para trabajar, ahora sabes mucho más de ambos, al menos eso espero. Si tienes el lujo de tener tiempo, te recomiendo seriamente implementar un sitio con cada uno. Entonces escribes tu propia experiencia de ellos dos y probablemente tu perspectiva resalte algunas cosas que a mi se me han pasado.
</p>
<p>La historia del documento <a href="http://github.com/anutron/jquery-vs-mootools/tree/master">puedes verla en github</a>.</p>
<p>
<script type="text/javascript" src="http://w.sharethis.com/button/sharethis.js#publisher=c327065b-efa0-4e12-afbc-5717f5cf62f9&type=website&post_services=facebook%2Cdigg%2Cdelicious%2Ctwitter%2Creddit%2Cfriendfeed%2Cmyspace%2Cybuzz%2Cstumbleupon%2Ctechnorati%2Cmixx%2Cblogger%2Cwordpress%2Ctypepad%2Cgoogle_bmarks%2Cwindows_live%2Cfark%2Cbus_exchange%2Cpropeller%2Cnewsvine%2Clinkedin"></script>
</p>
<hr/>
<p class="about">
About me: I am a <a href="http://www.mootools.net">MooTools</a> contributor and I blog about JavaScript and other things on my site <a href="http://www.clientcide.com">Clientcide</a> as well as release <a href="http://www.clientcide.com/js">numerous plug-ins for MooTools</a>. I am the author of <a href="http://www.amazon.com/gp/product/1430209836?ie=UTF8&tag=clientside-20&link_code=as3&camp=211189&creative=373489&creativeASIN=1430209836">MooTools Essentials</a> as well as the <a href="http://www.mootorial.com">MooTools online tutorial</a>. I work at a company in the SF Bay Area called <a href="http://www.cloudera.com">Cloudera</a>. <a href="http://www.clientcide.com/shout-out">I can be contacted thusly</a>.
</p>
<a name="discussion"></a>
<hr/>
<p class="about" style="color: #700"><strong>Una nota sobre comentarios aquí</strong>: Estos comentarios son moderados. Los comentarios no se mostraran hasta que no sean aprobados. Comentarios que no son productivos (ej. mal educados, insultos, ofensas, etc) no serán aprobados. Similarmente, comentarios "fanáticos" tampoco serán aprobados - ej. no "El framework es lo máximo! Es el mejor framework de todos!!" no son comentarios constructivos.
</p>
<script>
var disqus_url = "http://jqueryvsmootools.com/";
</script>
<div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/jqueryvsmootools/embed.js"></script>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-539314-11");
pageTracker._trackPageview();
} catch(err) {}</script>
<script type="text/javascript">
//<![CDATA[
(function() {
var links = document.getElementsByTagName('a');
var query = '?';
for(var i = 0; i < links.length; i++) {
if(links[i].href.indexOf('#disqus_thread') >= 0) {
query += 'url' + i + '=' + encodeURIComponent(links[i].href) + '&';
}
}
document.write('<script charset="utf-8" type="text/javascript" src="http://disqus.com/forums/jqueryvsmootools/get_num_replies.js' + query + '"></' + 'script>');
})();
//]]>
</script>
</body>
</html>