Robando Datos con Grease Monkey.
November 9, 2009
NOTA: Este contenido es por motivos educativos e informativos solamente.
Hace un par de días se me ocurrió que posiblemente se puede acceder a las cookies de un sitio web mediante greasemonkey. Al principio pensé que un agujero de seguridad tan grande no debió pasar por enfrente de los ojos de los desarrolladores del plugin sin ser notado, así que hice una pequeña prueba la cual consiste en crear un nuevo script que sea ejecutable en todos los sitios el cual contiene solo la siguiente instrucción:
alert(document.cookie);
Es super sencillo e inofensivo. Sin embargo, al correr un sitio web te das cuenta que en efecto greasemonkey puede acceder a las cookies de cualquier sitio web. Lo que puedes hacer con esas cookies depende mucho de tu creatividad, conocimiento y por supuesto, de la cookie en sí. Por ejemplo una cosa sencilla que hice fue simplemente redireccionar el navegador a una pagina donde la cookie se manda por correo a mi bandeja de entrada. Al probar ese script pude enviarme las cookies de twitter que mi navegador almacena. Un script bien configurado y dirigido para atacar una app especifica podría causar mucho daño, o por lo menos un buen susto. Lo mas obvio que puedes hacer con esto es robar información y ganar acceso a algunas cuentas de sitios web que usan cookies de forma irresponsable.
Redireccionar no es la forma más inteligente de robarte las cookies. Pero recordemos que greasemonkey no está sujeto a las mismas normas de seguridad que javascript corriendo directamente desde un sitio web. Digo esto por que hay que recordar que ajax no está sujeto a un solo dominio, sino que puede interactuar con documentos de distintos dominios al mismo tiempo, por lo que podemos usar el mismo script que yo hice para enviar el correo, pero en lugar de redireccionar y hacer el robo de datos demasiado obvio, podemos usar ajax y hacer la transferencia totalmente transparente al usuario.
Que se puede hacer al respecto?
La verdad es muy poco probable que te pase eso, a menos que alguien esté intencionalmente haciéndolo y ahí es donde está el problema. Por ejemplo alguien puede esconder el script malicioso dentro de algún otro script. Supongamos que quiero robar las cookies de facebook de alguna persona. Solo tendría que escribir un script que fuera útil para los usuarios de facebook y distribuirlo. El script ya tiene dentro la parte que hace el truco. Puedo disfrazarla de alguna u otra manera e incluso ofuscarla. Puedo incluso hacer que el script malicioso se active solo cuando esa persona en particular lo usa y así evitarme un montón de correos en mi bandeja que en realidad no quiero. Entonces que podemos hacer?
Una de las cosas más obvias es simplemente revisar los scripts que usas, aun que claro, eso puede ser un dolor de cabeza. Puedes por ejemplo usar un editor de textos que tenga capacidad para buscar y haces una búsqueda de ‘document.cookie’ para saber cuando un script esté accediendo a las cookies de tu navegador y ver que es lo que está haciendo con ellas. Otra cosa también es usar script confiables y como siempre investigar un poco antes de instalar un script. Pero aun así, recuerda revisarlo aun si nadie reporta nada raro. Esto por que por ejemplo, yo podría descargar un script muy popular, modificarlo y redistribuirlo asegurando que mucha más gente lo va a usar que un script que yo simplemente haya creado ayer por la tarde.
PD. Probablemnte muchos quieran ver los scripts que hice para enviarme cookies a mi correo. No lo comparto por que se que ahí afuera hay muchos script kiddies que probarán todo lo que encuentren para ‘hackear’. Además, los scripts son tan básicos que cualquiera que tenga conocimientos mínimos los puede desarrollar por si solo.
Ajax, creacion y empleo del objeto XMLHttpRequest
October 13, 2009
Continuando con la serie sobre ajax, veamos esta ocasión un ejemplo sencillo de la creación y el uso del objeto XMLHttpRequest, o XHR como se le conoce para abreviar. Quiero hacer notar que debido a la creciente actividad anti IE6 no quiero tratar los métodos de creación del objeto XMLHttpRequest en IE6, que generalmente requiere un try… catch. A partir de IE7, XMLHttpRequest es soportado de forma nativa, por lo que nos vamos a quedar con este método directo de acceso al objeto. Si te interesa brindar soporte para ajax en IE6, puedes buscar en la web sobre el tema.
Como una nota aparte, try… catch debería ser evitado por los problemas de desempeño que trae consigo.
Creando una nueva instancia:
Crear una nueva instancia de XHR es sumamente sencillo:
var miXHR = new XMLHttpRequest();
Con esto has creado una nueva instancia de XHR lista para ser usada, exprimida y explotada. Ahora, veamos la belleza de XHR en acción.
Para poder seguir el ejemplo, primero tienes que tener la siguiente preparación:
1)Un folder llamado ajax
2)Dentro del folder, un archivo de texto llamado texto.txt
3)Dentro del folder, un archivo HTML llamado ajax.html
4)Dentro del folder, un archivo js llamado ajax.js
El archivo de texto puede contener cualquier texto que tu quieras. El mio, por ejemplo contiene:
“Javascript doesn’t suck, you are just doing it wrong” Douglas Crockford.
Mi archivo HTML contiene tan solo el HTML necesario para ser considerado válido:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Ajax! Ah javascript ambiciosamente xtremo!!!</title>
<script type="text/javascript" src="ajax.js"></script>
</head>
<body>
<p id="ajaxPantalla"></p>
</body>
</html>
Y mi archivo Javascript esta completamente vacío… por el momento.
Eso es todo lo que necesitas por ahora. Empecemos a trabajar en nuestro javascript:
archivo: ajax.js
window.onload = function(){
//declaramos un event handler para el evento load de window.
}
Empezamos declarando un event handler para el evento load de window. Este nos va a permitir acceder al DOM cuando ya este totalmente cargado. El DOM, teóricamente, se termina de cargar antes de que el evento load de window sea activado, sin embargo, los métodos para poder detecta cuando el DOM ha sido cargado son, al momento de escribir este articulo, demasiado engorrosos y desde mi punto de vista no vale la pena recurrir a ellos por varias razones.
Nótese que estamos usando event handlres y no event listeners, esto es solo por comodidad, si quiere puedes usar event listeners, aun que en este ejemplo no creo que valga la pena pasar por todo el trabajo extra que eso requiere.
Continuando con nuestro ejemplo, procedamos a crear una instancia del objeto XHR y algunas variables extra que nos serán de utilidad:
archivo: ajax.js
funcion: window.onLoad
var xhr = new XMLHttpRequest();
var pantalla = document.getElementById('ajaxPantalla');
var initTime = new Date().getTime();
Empezamos por definir una nueva instancia de XMLHttpRequest, y la guardamos en una variable (xhr).
También tomamos una referencia a uno de los elementos en nuestro HTML y lo guardamos en otra variable (pantalla)
Por último, guardamos el tiempo actual en otra variable (initTime). Este ultimo paso es solo para poder ir monitorizando el tiempo que toman nuestras llamadas en ser procesadas. Al final capturaremos el tiempo de finalizado de la función y lo compararemos con el tiempo de inicio de la función para ver cuanto tiempo ha tomado el su procesamiento. Para ser mas “exactos” combendría mover la variable initTime justo al inicio, antes de xhr, de modo que el tiempo sea lo primero que se toma al iniciar la función. Sin embargo, yo lo he preferido dejar así.
Continuemos con nuestro ejemplo:
archivo: ajax.js
function: window.onload
if(xhr){
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//if(xhr.status == 200 || xhr.state == 304){
pantalla.innerHTML = xhr.responseText;
//}
}else{
//proveer mensajes para los diferentes codigos http.
}
}
xhr.open('GET','texto.txt',true);
xhr.send(null);
}else{
//proveer una alternativa a ajax si no está disponible.
}
Aquí es donde todo esta pasando. Primero chequeamos que efectivamente xhr esté disponible, de no ser así, proveemos un método alternativo:
if(xhr){
...
}else{
//proveer una alternativa a ajax si no esta disponible
}
En este ejemplo no vamos a hablar sobre alternativas, eso lo dejaremos para ejemplos mas adelante.
Si el primer if nos da true, entonces sabemos que xhr esta disponible, por lo que es seguro continuar.
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//if(xhr.status == 200 || xhr.state == 304){
pantalla.innerHTML = xhr.responseText;
//}else{
//proveer mensajes para los diferentes codigos http.
//}
}
}
xhr.open('GET','texto.txt',true);
xhr.send(null);
Lo primero que hacemos una vez determinado que el objeto xhr está disponible, es asignar una función a su evento readystatechange. Este evento se genera cada vez que el estado de la petición cambia. En esta ocasión no hablaremos de los diferentes estados de la petición, eso lo dejaremos para el siguiente artículo. Por ahora basta con que sepas que el cuarto estado es cuando la petición ha sido exitosa y nos ha regresado los resultados.
En un ejemplo real, o si estas corriendo los ejemplos en un localhost, puedes chequear el estado (status) de la respuesta (response). Si sabes algo de los códigos http, sabrás que 200 significa OK y 304 significa no modificado. En nuestro ejemplo chequeamos si el status de la respuesta es 200 o 304, lo que significa que el documento está disponible, de no ser así, enviamos mensajes diferentes dependiendo el código http de la respuesta. En este caso no hemos incluido esos mensajes, pero implementarlos no es difícil.
Una vez determinado que el status de la respuesta es 200 o 304, podemos imprimir el contenido de nuestro archivo txt a nuestra pantalla, para eso usamos innerHTML para asignar a pantalla el texto regresado por xhr.
xhr tiene dos diferentes tipos de respuesta: responseText y responseXML. Dependiendo de lo que estés pidiendo al servidor querrás usar uno u otro. La mayor parte del tiempo estarás usando responseText, por lo que en nuestros ejemplos nos mantendremos especialmente ligados a el.
Las ultimas dos lineas son las que en realidad hacen la petición:
xhr.open() toma mínimo dos parámetros, el método (GET o POST entre otros) y la url del recurso que queremos pedir (en nuestro caso ‘texto.txt’). El tercer parámetro determina si la petición es sincrónica o asíncrona. En nuestro caso, true, le dice al navegador que la petición debe ser asíncrona. En un futuro hablare de las diferencias entre peticiones sincrónicas y asíncronas, por el momento, basta con saber que la mayor parte del tiempo usaras true como tercer parámetro.
Como una nota aparte, el tercer parámetro no debería ser nunca false por problemas de desempeño.
xhr.open() también recibe otros dos parámetros (usuario y clave) para autentificación básica. Estos los usas cuando un sitio te pide una clave y contraseña. Por ejemplo, si vas a:
http://twitter.com/statuses/user_timeline.xml
te darás cuenta que el navegador te pide una clave y contraseña. Si estuvieras haciendo una petición vía ajax a una página similar, usarías los dos últimos parámetros para especificar tu usuario y contraseña. Toma en cuenta que esto no es recomendable ya que ajax es javascript y los archivos javascript pueden ser fácilmente vistos. Su uso puede ser para, por ejemplo, autentificar usuarios usando ajax donde tanto usuario como clave sean provistos por el usuario y no “hard codded” en el javascript.
xhr.send() sirve para enviar datos. En nuestro caso no estamos enviando nada, por lo que usamos null, habrá ocasiones cuando quieras enviar datos, por ejemplo para un sitio que requiere opciones como un índice de temas en un blog. En ejemplos futuros veremos como se usa send() para enviar datos. Por ahora, no es necesario.
Este ha sido un ejemplo sencillo del uso de ajax. En futuros artículos veremos ejemplos mas complejos y útiles. Habrás notado que en este ejemplo todo sucede cuando se carga la pagina, lo cual realmente no tiene sentido. EL objetivo es poder hacer las peticiones como respuesta al input del usuario ya sea hacer click en un enlace, un botón, o simplemente enviar un formulario.
Aquí esta el código completo, notaras que he agregado algunas variables y un par de lineas para medir el tiempo que tarda (en milisegundos) nuestra petición en ejecutarse. Es simplemente para poder ir manteniendo en mente un poco el desempeño de nuestras funciones.
archivo: ajax.js (completo):
window.onload = function(){
//declaramos un event handler para el evento load de window.
var xhr = new XMLHttpRequest();
var pantalla = document.getElementById('ajaxPantalla');
var initTime = new Date().getTime();
var finTime = null;
var totTime = null;
if(xhr){
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//if(xhr.status == 200 || xhr.state == 304){
pantalla.innerHTML = xhr.responseText;
finTime = new Date().getTime();
totTime = finTime - initTime;
alert(totTime + 'milisegundos');
//}
}else{
//proveer mensajes para los diferentes codigos http.
}
}
xhr.open('GET','texto.txt',true);
xhr.send(null);
}else{
//proveer una alternativa a ajax si no esta disponible.
}
}
Espero verlos en la siguiente entrega.
Explicando conceptos sencillos en muchas palabras. La importancia de entender bien los conceptos básicos de programación.
March 2, 2009
Algunas veces me pregunto por que a algunas personas les cuesta tanto entender los conceptos avanzados de la programación. Sería un poco arrogante decir que para mi es fácil y quizá un poco falso. Lo cierto es que algunas veces paso algunos minutos analizando algunos conceptos nuevos. Tengo la habilidad de entender conceptos abstractos y dibujar en mi mente los procesos por los que pasa una pieza de código dentro de su mecanismo, pero no creo que sea especial por eso. Es más, creo que cualquiera que quiera adquirir dicha habilidad puede hacerlo, solo es cuestión de entender bien los conceptos básicos de la programación.
El gran problema de nosotros los humanos, es que hemos relacionado lo básico con lo sencillo. Tenemos miedo a pasar horas pensando y analizando un concepto tan “sencillo” como lo es una variable o una función por que no queremos sentirnos como tontos al no entender que una variable es un pedazo de memoria en el que se puede almacenar un dato para ser usado en el futuro. La verdad es que no hay nada tonto en analizar más a profundidad el concepto. Yo mismo escribí un articulo enorme explicando simplemente tal concepto: las variables.
Si nos pusiéramos a pensar por un momento en el pasado y recordáramos nuestros inicios como programadores (los que ya llevamos algún tiempo), nos daríamos cuenta que estábamos tan ansiosos por llegar a la parte avanzada que simplemente corrimos antes de poder caminar. Dimos poca importancia a los conceptos básicos sin tomar en cuenta que esos conceptos básicos, como su nombre lo dice, serían la base de todo nuestro posterior conocimiento. El problema es entonces que la base ha quedado débil, y sin una estructura fuerte sobre la cual apoyar nuestro nuevo conocimiento y los nuevos conceptos, estos terminan cayendo al suelo y causando frustraciones que muchas veces nos hacen renunciar a nuestro trabajo.
Por tal motivo es importante detenernos unos instantes para comprender y explicar los conceptos básicos, pero no en pocas palabras. Al contrarío, dedicar un buen rato y buena parte de nuestra atención a dicho trabajo ya que una vez entendidos estos conceptos fundamentales de la programación no será más fácil comprender conceptos más abstractos y complejos. Tomemos como ejemplo los closures en javascript. Alguien que no ha entendido bien un concepto tan básico como las variables locales y globales puede tener mayor dificultad para entender los closures que una persona que ha comprendido la diferencia entre variables locales y globales.
Cuando yo empece a aprender sobre programación puse especial atención a los elementos básicos del lenguaje (en aquel tiempo Javascript) y me aseguré de que la base sobre la que descansaría todo mi futuro conocimiento fuese sólida y estable. Creo que ese ha sido mi secreto en mi desarrollo como programador y aconsejaría sin temor a equivocarme a todo aquel que esté interesado en programación que haga lo mismo. Asegúrate de que tus conceptos elementales estén bien fundamentados. Asegúrate de encontrar a aquellos que ponen énfasis en ese aspecto, a esos que explican en muchas palabras los conceptos más elementales de la programación.
Javascript Orientado a Objetos sgun Buzu -Object Literal Notation
December 31, 2008
Siguiendo con la construcción de los objetos, esta ocasión hablaré sobre otra forma muy común de construir objetos. Me refiero a Object Literal Notation (OLN).
OLN es una forma de escritura que se popularizó gracias al surgimiento de JSON, un “formato ligero para el intercambio de datos” (Wikipedia). OLN es una forma de escribir javascript, o más concreto, objetos en javascript usando un conjunto de pares conocidos como propiedad y valor. Para construir un objeto usando OLN es suficiente con hacer lo siguiente:
var Buzu = {
nombre: 'buzu',
hablar: function(){
alert('Amor, paz, respeto y libertad -Revolución');
}
}
Lo que acabamos de hacer es crear un objeto similar al que creamos en la entrega anterior de esta serie. Podrás ver que esta forma de crear objetos es mucho más compacta. Sin embargo, tiene sus desventajas. Una de ellas es que los objetos que se crean de esta manera no son fácilmente instanciables, por lo que se puede decir que no son la mejor opción si se piensa en re-usar los objetos al mismo tiempo o tener varias instancias del mismo objeto al mismo tiempo.
Este tipo de escritura esta siendo usado últimamente para crear una especie de pseudonamespaces para asegurar que diferentes librerías no “choquen” entre si causando errores. El uso de esta técnica no es muy difundido aun especialmente entre la comunidad latina de desarrolladores o programadores en javascript, sin embargo es cada vez más usada.
Para lograr esa especie de namespaces simplemente se necesita “encerrar” todas nuestras funciones dentro de una función auto ejecutable, es decir, una función que se ejecuta inmediatamente después de haber sido leída. Ej:
(function(){
if(!window.b){window['b'] = {} }
function alertar(que){
alert(que)
}
window['b']['alertar'] = alertar;
}
)();
De esa manera para poder acceder a la función alertar, es necesario poner la siguiente instrucción:
b.alertar('hola mundo');
De este modo aun que alguna otra librería que se esté usando contenga una función llamada alertar, será muy difícil que esta genere problemas con la nuestra.
Esta técnica es especialmente útil si se quiere distribuir una librería o trabajar con varias librerías en el mismo proyecto.
En la siguiente entrega del esta serie aplicaremos lo que hemos aprendido hasta ahora creando una librería pequeña a la cual podrás ir agregando más funciones conforme las valla necesitando. Esa será probablemente la última entrega de esta serie y explicaré temas de suma importancia, especialmente la diferencia entre métodos públicos, privados y privilegiados. Será una entrega larga y con mucha info.
Hasta entonces!
Javascript Orientado a Objetos segun Buzu -El constructor de objetos
December 16, 2008
Otra entrega de esta serie. Primero pido disculpas por haber tardado tanto en publicar este articulo. Estuve un poco ocupado los días anteriores.
Esta ocasión hablaré sobre como crear objetos. Prometo que de ahora en adelante estaremos escribiendo más código que en entregas anteriores.
Primero que nada hay que saber que hay básicamente dos formas de crear objetos en javascript. La primera es usando el constructor de objetos y la segunda es usando Javascript Literal Notation (JLN). Para muchos no hay realmente diferencia entre si usas JLN o el constructor de objetos. Sin embargo, la realidad es que hay mucha diferencia.
Para lograr entender la diferencia, primero necesitas saber que la programación orientada a objetos en javascript no está basada en clases como en muchos otros lenguajes, sino en prototipos. Un prototipo es una plantilla a partir de la cual se crean los objetos. Estos pueden ser extendidos y asociados a más de un objeto logrando simular el concepto de la herencia de los lenguajes basados en clases.
La importancia de los prototipos es que estos no se copian cada vez que se crea una nueva instancia de determinado objeto (hace tiempo participé en una interesante charla en la que se discutía si en realidad existen las instancias en js o no. Les recomiendo la lean), mas bien, estos son parte del objeto base y pueden ser accedidos por sus instancias.
Veamos un ejemplo de construcción de un objeto usando el constructor de objetos.
var Buzu = function(nombre){
this.nombre = nombre;
}
Buzu.prototype.saludar = function(saludo){
alert(saludo);
}
Como puedes ver, ahí estoy usando el constructor de objetos para crear un objeto base llamado Buzu. -Es costumbre iniciar los nombre de los objetos con mayúsculas-. Este objeto ya “viene” con un prototipo, es algo así como el motor del objeto, o para los más románticos, el corazón del objeto. Este prototipo puede ser modificado y eso es precisamente lo que saludar está haciendo.
Al agregar la función saludar, lo que en realidad estamos haciendo es agregar una método al prototipo de Buzu.
Ahora que ya tenemos nuestro objeto base, podemos crear instancias fácilmente de la siguiente manera:
var ImBuzu = new Buzu('Buzu');
ImBuzu.saludar('Amor, paz, respeto y libertad -Revolución');
Ahí estamos creando una instancia de Buzu. En otras palabras, ImBuzu es un objeto basado en Buzu, por lo que tiene todas su propiedades y métodos, así como los de su prototipo. Está es una de las formas más recomendables de crear objetos.
En el siguiente articulo hablaré de JLN y sus ventajas y desventajas frente al uso del constructor de objetos que hemos tratado en esté articulo.
Javascript orientado a objetos segun Buzu -Los Objetos
December 4, 2008
Después de la “corta” explicación acerca de las variables que hiciera en el primer post de esta serie, creo que es necesario empezar a adentrarnos más en la zona de los objetos.
Hablar de objetos es hablar de algo de todos los días. Si has buscado pro la web acerca de los objetos en javascript, te habrás dado cuenta que en un sin numero de sitios los comparan con objetos en la vida real, así que no usaré esa comparación por considerarla demasiado trillada. Me limitaré a decirte que los objetos en javascript se componen principalmente de dos cosas: métodos y propiedades.
Los Métodos:
Los métodos son todas aquellas acciones que un objeto puede realizar. Así, el objeto window (un objeto ya incluido en javascrip que hace referencia a la ventana del navegador) posee el método close cuya función es cerrar la ventana.
Para acceder a los métodos de un objeto se usan diferentes notaciones de las cuales la más popular es la notación de punto (.). De este modo, para acceder al método close del objeto window basta con la siguiente instrucción:
window.close();
Estoy seguro que ya habías visto eso anteriormente, y es eso a lo que me refería cuando dije que hablar de objetos es hablar de algo de todos los días. Muchos empezamos a usar objetos aun antes de saber siquiera lo que era un objeto.
Así como hay más de una manera de acceder a un método, también hay más de una manera de crearlos. Pero ese es material que dejaremos para el siguiente articulo ya que quiero explicarlo junto con las diferentes formas de crear objetos.
Las propiedades:
Las propiedades de un objeto son algo similar a los métodos, solo que estas no realizan acción alguna. Su único objetivo es almacenar valores correspondientes al objeto. Dichos valores pueden ser accesados de la misma manera en que accedemos a los métodos. Ya explique la notación de punto. Ahora explicaré la notación de corchetes.
Para acceder a una propiedad o a un método usando la notación de corchetes, vasta con poner el nombre de la propiedad o método dentro de corchetes antecedido por el nombre del objeto cuya propiedad o método queremos acceder. De este modo tenemos que
window.width es lo mismo que window['width']
Como habrás notado, el nombre dentro de los corchetes va entrecomillado, esto es por que ese valor es un string muy similar al de los llamados array relacionales. Esta notación es muy rara, pero muy poderosa.
En siguientes artículos veremos más acerca de esta notación y de sus usos en la vida real. Notarás que puede sacarnos de muchos líos y facilitarnos la vida.
Una vez más, si tienes alguna duda, no dudes en dejar tu comentario.
Javascript orientado a objetos segun Buzu
November 28, 2008
No es novedad que soy un javascripter de hueso colorado. A lo largo de esta carrera por la lucha contra las incompatibilidades entre navegadores, la falta de soporte de los estándares y otros malestares propios del programador que opta por las tecnologías de lado del cliente, he aprendido un montón de cosas, pero una de las mas valiosas es que no hay como un buen objeto. Sin embargo, es necesario un conocimiento robusto y con buenas bases acerca de la tecnología y sus agujeros para poder crear objetos que sean realmente funcionales.
A lo largo de este tiempo, también me he dado cuenta que hay muchos que no tiene ni idea de la programación con objetos y sus beneficios. Muchos cuando tratan de empezar se encuentran con que no hayan por donde empezar y parece que todos los buenos tutos están en inglés. Por esta razón me he decidido escribir esta serie de tutoriales esperando que puedan ser una puerta de entrada al mundo de OOP en javascript. Quiero dejar claro que esta no es una serie de tutoriales para novatos en el mundo de javascript y por lo tanto no me detendré a explicar conceptos que creo demasiado básicos. Sin embargo, y en contraste con lo que acabo de decir, si me detendré un momento a explicar algunos puntos sobre las variables, ya que las eh encontrado base fundamental de los objetos. Me quedo abierto a tus dudas. Si hay algo que no entiendes, no dudes en dejar un mensaje y yo te respondo.
Espero recibir un poco de feedback ya que es eso lo muchas veces alienta a seguir escribiendo.
Primero que nada hablemos sobre variables y por que son importantes en la creación y el entendimiento de como funcionan los objetos.
Las variables son como pequeñas cajitas que nos sirven para guardar valores ya sea numéricos, alfanuméricos, boleanos (falso, verdadero), e incluso funciones y objetos. Piensa en una variable como un papelito en el que escribes una nota para poder recordarla en otro momento.
La importancia de las variables en la programación orientada a objetos (OOP) es que estas nos ayudan a guardar valores que son fundamentales para el funcionamiento de los objetos. Sin variables no hay nada más. El problema con las variables es que muchas veces las vemos como simples valores, cuando en realidad son la base de un buen objeto.
Entender el concepto de las variables y sus distintas formas de comportarse según el ambiente en el que están, es fundamental para entender otros conceptos mas abstractos como el caso de los closures, al cual nos acercaremos en artículos posteriores.
Hay diferentes formas de declarar una variable y distintos lugares en los cuales hacerlo y estos determinan el comportamiento de una variable. Veamos primero las formas de hacerlo:
Usando var:
Usar la palabra var es una de las formas mas comunes de crear una variable. Es tambien una de las razones de algunos problemas de novato, pero que hasta los desarrolladores experimentados cometemos alguna vez. Lo que pasa es que usando la palabra var, creamos una variable local al territorio en el que nos encontramos. Ah si, olvide mencionar que hay varios “territorios”, pero creo que eso lo explica mejor una imagen.

De este modo tenemos que daca función define su propio territorio. Para ser sincero no se si se les llama territorios, en Inglés (el lenguaje en el que he aprendido casi todo lo que se) se les llama scope.
Una variable declarada con var dentro de la función moveLinks no puede ser accesada desde otra función al mismo nivel o un nivel mas arriba de moveLinks por que la variable es local al territorio de moveLinks. En otras palabras, esta contenida dentro de ese territorio y no puede salir de ahi. Ah si, otra vez olvidé mencionar que también hay niveles y de nuevo, eso quizá lo explica mejor un imagen.

De este modo, la variable “extra”, declarada dentro de la función init, al ser declarada con la palabra var, no puede ser accesada desde addEvent o mOver (las otras dos funciones en negro) debido a que estas están al mismo nivel de init y no pueden acceder una variable local que no sea local a ellas mismas o a un función declarada un nivel mas arriba dentro del mismo territorio. Se que suena confuso, pero es muy sencillo una vez que captas la idea principal.
Ese concepto que acabo de explicar es uno de los conceptos que es necesario entender para poder darle con duro a los closures, así que te recomiendo que lo analices bien y de nuevo, si tienes dudas, deja un comentario y yo te contesto.
En resumen, tenemos que una variable declarada con var es local a la función en que dicha variable fue declarada, esta “presa” dentro del terriotorio de dicha función y no puede ser accesada (en teoría) mas que por la función en donde fue creada o una funciona en un nivel mas abajo de dicha función que esté contenida dentro del territorio de la función en que la variable fue creada. En otras palabras, una función contenida dentro de la función en donde la variable fue creada. Eso fue mas fácil no?
Te preguntarás por que he puesto entre paréntesis “en teoría”. Esto es por que si hay formas de acceder a una variable local desde fuera de la función en la que esta fue creada, pero eso lo veremos después.
Sin usar var
Cuando no usas var, la cosa es mas sencilla, pero menos recomendable desde un punto de vista OOP. Toda variable declarada sin usar la palabra var es global y puede ser accesada desde cualquier lugar.
Esta sea quiza la explicacion de la diferencia entre usar var y no usar var mas larga que hayas leido, pero como lo he dicho ya, entender esta diferencia es clave si realmente quieres aprender OOP en javascript. En siguientes articulos de la serie estaré tratando temas más interesantes. Por ahora eso es todo.
Invertir una lista usando Javascript
November 25, 2008
Hace un rato estaba desarrollando un sitio y me encontré con un indeseado efecto. Cuando posicionaba mi menú, el cual es una lista desordenada, se me invertían los elementos. El menú se suponía debía quedar as:
Home | About Us | Contact
Pero quedaba así:
Contact | About Us| Home
La razón de ese efecto es muy simple. Al posicionar mi menú estoy usando float: right, ya que quiero que este quede alineado a la derecha. Lo que sucede entonces es que me toma el primer elemento (HOME) y lo posiciona a la derecha del siguiente elemento (About Us) de modo que nos queda About Us | (Home). Luego posiciona About Us a la derecha del siguiente elemento (Contact) quedando: Contact | About Us | Home
La solución más sencilla, y por la que muchos novatos y no tan novatos habrían optado, es invertir la lista desordenada, pasando de:
<ul id="menu"> <li><a href="index.php" title="Go to the home page">HOME</a></li> <li><a href="about.php" title="Read about Bilt-Tuff">ABOUT US</a></li> <li><a href="contact.php" title="View our contact information and contact form">CONTACT</a></li> </ul>
a
<ul id="menu"> <li><a href="contact.php" title="View our contact information and contact form">CONTACT</a></li> <li><a href="about.php" title="Read about Bilt-Tuff">ABOUT US</a></li> <li><a href="index.php" title="Go to the home page">HOME</a></li> </ul>
De modo que al ser flotados, los elementos se posicionaran en el orden correcto. Sin embargo, nosotros, los experimentados
, sabemos que no es buena idea modificar el XHTML para lograr dicho efecto. La razón del por que no es buen idea es por que eso nos desacomoda todo el enmarcado poniéndolo en orden inverso. Esa no es una buena idea. El enmarcado debe estar siempre en el orden correcto para asegurar un fácil manejo, mantenimiento y actualización del proyecto.
Yo opte por usar Javascript como solución. Hice esta sencilla función:
function invertir(){
var menu = document.getElementById('menu');
var nuevoOrden = new Array();
for(i=0, j=menu.getElementsByTagName('li'); j[i]; i++){
var liActual = j[j.length - (i+1)];
nuevoOrden.push(liActual);
}
menu.innerHTML = "";
for(i=0; nuevoOrden[i]; i++){
menu.innerHTML += "<li>" + nuevoOrden[i].innerHTML + "<\/li>";
}
}
Es función se ejecuta cuando la página termina de cargarse. Todavía está en etapa de desarrollo, pero es un buen comienzo para algo más grande. La expongo aquí por si pueda servir como inspiración o base para algún otro proyecto. Si empiezas a hacer algo basado ya sea en la idea de la función o la función me gustaría saberlo. Quizá podamos compartir ideas.
Lo único que esa función hace es tomar el ultimo elemento de la lista, lo guarda en un array de modo que el último elemento en la lista es el primero en el array, luego toma el penúltimo elemento de la lista y lo guarda en la segunda posición del array y así sucesivamente permitiéndonos invertir los elementos. Luego “limpia” la lista e inserta en ella los elementos que han sido invertidos y guardados en el array.
La funcion usa Javascript en bruto por ahora, pero el proyecto final usará la delicadesa y presicion del DOM.
Inner HTML al desnudo.
July 27, 2008
este post fue primero publicado en forosdel web despues de haver notado la duda en muchos usuarios hacerca de innerHTML. Sin mas, aqui el post.