Length en Javascript

28 Feb 2011

En Javascript, el comando length es uno de los más utilizados. Para todos los desarrolladores, length es una de las piezas claves a la hora de recorrer arrays. Sin embargo, además de como una propiedad, funciona también como un interesante método aplicable a funciones que permite construir arquitecturas de objetos muy flexibles. Repasemos todos sus usos con sus correspondientes ejemplos en cada caso:

Length En cadenas ( String )

El valor de la propiedad length en una cadena es igual a su número de caracteres.

Sin embargo, hay que tener en cuenta que el UTF-16, el formato para cadenas utilizado en Javascript, utiliza una codificación de 16 bits para representar los caracteres más usuales; en el caso de aquellos más raros, se necesitan dós unidades de código por lo que puede darse el caso de que el valor length no se corresponda exactamente con el número de caracteres utilizados en una cadena.

var foo = 'Hello World'; 
console.log( foo.length ); // 11
 
var bar = '\uD834\uDD1E'; // MUSICAL SYMBOL G CLEF (D834 y DD1E) 
console.log( bar.length ); // 2

Length en arrays ( Array )

En un array, la propiedad length devuelve el número de elementos que contiene, independientemente de si se tratan tanto de valores falsy como truthly:

var foo = [ 0, 1, 2, '', 'foo', false, undefined, NaN, Infinity, [], {} ];
console.log( foo.length  ); // 11

Editando esta propiedad, podemos truncar un Array en cualquier momento:

var foo = [ 1, 2, 3, 4, 5, 6, 7 ];
foo.length = 3;
 
console.log( foo ); // 1, 2, 3

Sin embargo, una vez truncado, ampliar la longitud del array no produce ningún efecto:

foo.length = 6;
console.log( foo ); // 1, 2, 3

Como hemos mencionado al principio, length es el comando clave para recorrer un array en Javascript:

var foo = [ 1, 2, 3, 4, 5, 6 ];
 
for( i = 0, j = foo.length; i < j; i++ ){  
  foo[ i ] = foo[ i ] * 2; // multiply each value by 2
}
 
console.log( foo ); // [2, 4, 6, 8, 10, 12]

En números y objetos ( Number y Object )

Las variables primitivas Number y Object  no tienen propiedad length y devuelven por tanto undefined:

var foo = 12;
var bar = { id : '12' };
 
console.log( foo.length ); // undefined
console.log( bar.length ); // undefined

En funciones ( Function )

En el caso de las funciones, length no es una propiedad sino un método. Invocado directamente sobre el nombre de una función declarada, devuelve el número de argumentos que espera:

var foo = function( param1, param2, param3 ){
  // Do something...
}
 
console.log( foo.length ); // 3

Invocada en el interior de la misma, puede darnos el número de argumentos que se han pasado a través de arguments:

var foo = function(){
  return arguments.length;
}
 
console.log( foo( 'param1', 'param2', 'param3', 'param4' ) ); // 4

Conociendo ambos datos, podemos crear una función que nos permita sobreescribir métodos dependiendo de los valores que tengamos:

function addMethod(object, name, fn){ 
  // Save a reference to the old method 
  var old = object[ name ]; 
 
  // Overwrite the method with our new one 
  object[ name ] = function(){
    // Compare incoming arguments with expected
 
    if ( fn.length == arguments.length ) {
 
      // If there was a match, run the function
      return fn.apply( this, arguments );
 
    } else if ( typeof old === "function" ) {
 
      // Otherwise, fallback to the old method
      return old.apply( this, arguments );
 
    }
  };
}

Tomemos ahora un objeto con varios métodos de igual nombre que devolverán un valor u otro dependiendo de los argumentos:

function Users(){
  var users = [ 'Philip K Dick', 'Isaac Asimov', 'Philip J Farmer', 'Orson Scott Card' ];
 
  // No arguments
  addMethod( this, 'find', function(){
    return users;
  });
 
  // One argument
  addMethod( this, 'find', function( name ){
    var retUsers = [];
    for ( var i = 0; i < users.length; i++ ){
      if( users[ i ].indexOf( name ) == 0 ){
        retUsers.push( users[ i ] );
      }
    }
    return retUsers;
  });
 
  // Two arguments
  addMethod( this, 'find', function( first, last ){
    var retUsers = [];
    for( var i = 0; i < users.length; i++ ){
      if( 
        ( users[ i ].indexOf( first ) != -1 ) && 
        ( users[ i ].indexOf( last ) != -1) ){
          retUsers.push( users[ i ] );
      }
    }
    return retUsers;
  });
}
var users = new Users();
 
console.log( users.find() ); // ["Philip K Dick", "Isaac Asimov", "Philip J Farmer", "Orson Scott Card" ]
console.log( users.find( 'Isaac' ) ); // ["Isaac Asimov"]
console.log( users.find( 'Philip' ) ); // ["Philip K Dick", "Philip J Farmer"]
console.log( users.find( 'Orson', 'Card' ) ); // ["Orson Scott Card"]
console.log( users.find( 'William', 'Farmer' ) ); // []

En el ejemplo anterior, hemos creado tres métodos con el mismo nombre pero con un comportamiento diferente basado en el número de argumentos. Esto ofrece una gran flexibilidad a la hora de crear arquitecturas de objetos complejos que puede resultar interesante de explotar.

Y hasta aquí este análisis sobre el comando length. Si tenéis más ejemplos de uso interesantes, no dudéis en compartirlos en los comentarios!

Más:

{4} Comentarios.

  1. Kcire87

    Excelente pagina, muy util para los que gustan de programar en JavaScript…

    Saludos

  2. ger7893

    Excelente me ha ayudado mucho ya que estoy comenzando en javascript 😛

  3. Mateo Aluerd

    Acabo de flipar con el ejemplo de length en funciones y como se crean un mismo método para diferentes argumentos. Mucho debería interiorizar yo este ejemplo para extrapolarlo a otros casos, pero tiene una pinta con mucho potencial. De momento este caso concreto me habría resultado más fácil de entender y hacer con alguno de los patrones que explicas en otros posts. Por ejemplo este: http://jsfiddle.net/QpZx2/

  4. Joaquim

    ¿Por qué no me funciona el operador lenght?
    He copiado el ejemplo de lenght en cadenas y también en arrays y en los dos casos me ha salido undefined.

    Gracias

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *