Funciones

Weitergeleitet von https://developer.mozilla.org/de/docs/JavaScript/javascript_guide/Funktionen

Las funciones son uno de los pilares fundamentales en JavaScript. Una función es un procedimiento JavaScript—un conjunto de declaraciones que realiza una tarea o calcula un valor. Para usar una función, debes definirla en algún lugar del ámbito desde el cual deseas llamarla.

Definición de funciones

La definición de una función (también llamada declaración de función) consiste en la palabra clave (reservada)  function, seguida por:

  • El nombre de la función (opcional).
  • Una lista de argumentos para la función, encerrados por paréntesis y separados por coma (,).
  • Las declaraciones JavaScript que definen la función, encerradas por llaves, { }.

Por ejemplo, el siguiente código define una función simple llamada  square:

function square(number) {
  return number * number;
}

La función square toma un argumento, llamado number. La función consiste de una sentencia que dice "retorna el argumento de la función (que es, number) multiplicado por si mismo. La sentencia return especifica el valor retornado por la función.

return number * number;

Los parámetros primitivos (como un número) son pasados a las funciones por valor; el valor es pasado a la función, pero si la función cambia el valor del parámetro, este cambio no es reflejado globalmente o en otra llamada a la función.

Si le pasas un objecto (i.e. a non-primitive value, como un Array o un objecto definido por el usuario) como parámetro, y la función cambia las propiedades del objeto, este cambio es visible desde fuera de la función, como se  ve en el siguiente ejemplo:

function myFunc(theObject) {
  theObject.make = "Toyota";
}

var mycar = {make: "Honda", model: "Accord", year: 1998},
    x,
    y;

x = mycar.make;     // x gets the value "Honda"

myFunc(mycar);
y = mycar.make;     // y gets the value "Toyota"
                    // (the make property was changed by the function)

Tenga en cuenta que asignar un nuevo objeto al parámetro no tendrá ningún efecto fuera de la función, porque esto está cambiando el valor del parámetro en lugar de una de las propiedades del objeto:

function myFunc(theObject) {
  theObject = {make: "Ford", model: "Focus", year: 2006};
}

var mycar = {make: "Honda", model: "Accord", year: 1998},
    x,
    y;

x = mycar.make;     // x gets the value "Honda"

myFunc(mycar);
y = mycar.make;     // y still gets the value "Honda" 

En el primer caso, el objeto mycar fue pasado a la función myFunc, que lo modifica. En el segundo caso, la función no modifica el objeto que fue pasado; en su lugar, crea una nueva variable local que pasa a tener el mismo nombre que el objeto global pasado, por lo que no hay ningún efecto en el objeto global.

Si bien las declaraciones de la función anterior son sintácticamente una declaración, las funciones puede tambier ser creadas por una expresión de función. Tal función puede ser anónima; no tiene que tener un nombre. Por ejemplo, la función0 square podría haberse definido:

var square = function(number) {return number * number};
var x = square(4) //x gets the value 16

Sin embargo, se puede proporcionar un nombre con una expresión de función, y puede ser usado dentro de la función para referirse a sí misma, o en un debugger para identificar la función en el seguimiento de la pila:

var factorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};

print(factorial(3));

La expresión de funciones son convenientes cuando se le pasa una función como argumento a otra función. El siguiente ejemplo muestra una función map que se define a continuación y luego se la llama con una función anónima como primer parámetro:

function map(f,a) {
  var result = [], // Create a new Array
      i;
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
  return result;
}

El siguiente código:

map(function(x) {return x * x * x}, [0, 1, 2, 5, 10]);

retorna [0, 1, 8, 125, 1000].

En JavaScript, una función puede ser definida en base a una condición. Por ejemplo, la siguiente definición de función define (redundancia) myFunc sólo si num es igual a 0:

var myFunc;
if (num == 0){
  myFunc = function(theObject) {
    theObject.make = "Toyota"
  }
}

Además de definir funciones como se describe aquí, puedes usar el Function constructor para crear funciones de una cadena en tiempo de ejecución, igual a eval().

Un método es una función que es propiedad de un objeto. Lea más acerca de objetos y métodos en Working with Objects.

Llamando funciones

Definir una función no la ejecuta. Definir una función simplemente la nombra y especifica que hacer cuando la función es llamada. Llamar la función realiza las acciones especificadas con los parámetros indicados. Por ejemplo, si defines la función  square, podrías llamarla como sigue:

square(5);

La declaración anterior llama a la a función con el argumento 5. La función ejecuta sus declaraciones y retorna el valor 25.

Las funciones deben estar en el ámbito (scope) cuando ellas son llamadas, pero la declaración de la función puede estar por debajo de la llamada, como muestra el siguiente ejemplo:

print(square(5));
/* ... */
function square(n){return n*n} 

El alcance de una función es la función en la que está declaradad, o el programa entero, si está declarada en el nivel superior. Tenga en cuenta que esto funciona sólo cuando se define la función usando la sintaxis anterior (i.e. function funcName(){}). El código siguiente no funcionará.

print(square(5));
square = function (n) {
  return n * n;
}

The arguments of a function are not limited to strings and numbers. You can pass whole objects to a function, too. The show_props function (defined in Working with Objects) is an example of a function that takes an object as an argument.

A function can be recursive; that is, it can call itself. For example, here is a function that computes factorials recursively:

function factorial(n){
  if ((n == 0) || (n == 1))
    return 1;
  else
    return (n * factorial(n - 1));
}

You could then compute the factorials of one through five as follows:

var a, b, c, d, e;
a = factorial(1); // a gets the value 1
b = factorial(2); // b gets the value 2
c = factorial(3); // c gets the value 6
d = factorial(4); // d gets the value 24
e = factorial(5); // e gets the value 120

There are other ways to call functions. There are often cases where a function needs to be called dynamically, or the number of arguments to a function vary, or in which the context of the function call needs to be set to a specific object determined at runtime. It turns out that functions are, themselves, objects, and these objects in turn have methods (see the Function object). One of these, the apply() method, can be used to achieve this goal.

Function scope

Variables defined inside a function cannot be accessed from anywhere outside the function, because the variable is defined only in the scope of the function. However, a function can access all variables and functions defined inside the scope in which it is defined. In otherwords, a function defined in the global scope can access all variables defined in the global scope. A function defined inside another function can also access all variables defined in it's parent function and any other variable to which the parent function has access.

// The following variables are defined in the global scope
var num1 = 20,
    num2 = 3,
    name = "Chamahk";

// This function is defined in the global scope
function multiply() {
  return num1 * num2;
}

multiply(); // Returns 60

// A nested function example
function getScore () {
  var num1 = 2,
      num2 = 3;
  
  function add() {
    return name + " scored " + (num1 + num2);
  }
  
  return add();
}

getScore(); // Returns "Chamahk scored 5"

Closures

Los Closures son una de las características más poderosas de JavaScript. JavaScript permite el anidamiento de funciones y, además, otorga a la función interior acceso completo a todas las variables y funciones definidas dentro de la función externa (y todas las otras variables y funciones a la cual la función externa tiene acceso). Sin embargo, la función exterior no tiene acceso a las variables y funciones definidas dentro de la función interior. Esto proporciona un tipo de seguridad a las variables de la función interna. Además, dado que la función interna tiene acceso al ámbito de la función externa, las variables y funciones definidas en la función externa vivirán más tiempo que la función externa en sí misma, si la función interna se las arregla para sobrevivir más allá de la vida de la función externa. El cierre (closure) se crea cuando la función interna de alguna manera está a disposición de cualquier ámbito fuera de la función externa.

var pet = function(name) {          // The outer function defines a variable called "name"
      var getName = function() {
        return name;                // The inner function has access to the "name" variable of the outer function
      }

      return getName;               // Return the inner function, thereby exposing it to outer scopes
    },
    myPet = pet("Vivie");
    
myPet();                            // Returns "Vivie"

Puede ser mucho más complejo que el código anterior. Un objeto que contiene métodos para manipular las variables internas de la función externa puede ser retornado.

var createPet = function(name) {
  var sex;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
pet.getName();                  // Vivie

pet.setName("Oliver");
pet.setSex("male");
pet.getSex();                   // male
pet.getName();                  // Oliver

En el código anterior, la variable name de la función externa es accesible desde las funciones internas, y no hay otra forma de acceder a las variables internas excepto a través de las funcines internas. Las variables internas de la función interna actúan como almacenes seguros para las funciones internas. Mantienen "persistente", pero segura, la información con la que necesitan trabajar las funciones internas. Las funciones incluso no tienen que ser asignadas a una variable, o tener un nombre.

var getCode = (function(){
  var secureCode = "0]Eal(eh&2";    // A code we do not want outsiders to be able to modify...
  
  return function () {
    return secureCode;
  };
})();

getCode();    // Returns the secret code

Hay, sin embargo, una serie de peligros a tener en cuenta al usar closures. Si una función de cierre define una variable con el mismo nombre que una variable del ámbito exterior, no hay forma de hacer referencia al ámbito de la variable exterior.

var createPet = function(name) {  // Outer function defines a variable called "name"
  return {
    setName: function(name) {    // Enclosed function also defines a variable called "name"
      name = name;               // ??? How do we access the "name" defined by the outer function ???
    }
  }
}

La variable mágica this es muy tramposa en los closures. Debe ser usada cuidadosamente, la referencia a this depende completamente de dónde se llama la función, en lugar de dónde se define. Un excelente y elaborado artículo sobre closures puede encontrarse here.

Using the arguments object

The arguments of a function are maintained in an array-like object. Within a function, you can address the arguments passed to it as follows:

arguments[i]

where i is the ordinal number of the argument, starting at zero. So, the first argument passed to a function would be arguments[0]. The total number of arguments is indicated by arguments.length.

Using the arguments object, you can call a function with more arguments than it is formally declared to accept. This is often useful if you don't know in advance how many arguments will be passed to the function. You can use arguments.length to determine the number of arguments actually passed to the function, and then access each argument using the arguments object.

For example, consider a function that concatenates several strings. The only formal argument for the function is a string that specifies the characters that separate the items to concatenate. The function is defined as follows:

function myConcat(separator) {
   var result = "", // initialize list
       i;
   // iterate through arguments
   for (i = 1; i < arguments.length; i++) {
      result += arguments[i] + separator;
   }
   return result;
}

You can pass any number of arguments to this function, and it concatenates each argument into a string "list":

// returns "red, orange, blue, "
myConcat(", ", "red", "orange", "blue");

// returns "elephant; giraffe; lion; cheetah; "
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// returns "sage. basil. oregano. pepper. parsley. "
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

Please note that the arguments variable is "array-like", but not an array. It is array-like in that is has a numbered index and a length property. However, it does not possess all of the array-manipulation methods.

See the Function object in the JavaScript Reference for more information.

Predefined functions

JavaScript has several top-level predefined functions:

The following sections introduce these functions. See the JavaScript Reference for detailed information on all of these functions.

eval Function

The eval function evaluates a string of JavaScript code without reference to a particular object. The syntax of eval is:

eval(expr);

where expr is a string to be evaluated.

If the string represents an expression, eval evaluates the expression. If the argument represents one or more JavaScript statements, eval performs the statements. The scope of eval code is identical to the scope of the calling code. Do not call eval to evaluate an arithmetic expression; JavaScript evaluates arithmetic expressions automatically.

isFinite function

The isFinite function evaluates an argument to determine whether it is a finite number. The syntax of isFinite is:

isFinite(number);

where number is the number to evaluate.

If the argument is NaN, positive infinity or negative infinity, this method returns false, otherwise it returns true.

The following code checks client input to determine whether it is a finite number.

if(isFinite(ClientInput)){
   /* take specific steps */
}

isNaN function

The isNaN function evaluates an argument to determine if it is "NaN" (not a number). The syntax of isNaN is:

isNaN(testValue);

where testValue is the value you want to evaluate.

The parseFloat and parseInt functions return "NaN" when they evaluate a value that is not a number. isNaN returns true if passed "NaN," and false otherwise.

The following code evaluates floatValue to determine if it is a number and then calls a procedure accordingly:

var floatValue = parseFloat(toFloat);

if (isNaN(floatValue)) {
   notFloat();
} else {
   isFloat();
}

parseInt and parseFloat functions

The two "parse" functions, parseInt and parseFloat, return a numeric value when given a string as an argument.

The syntax of parseFloat is:

parseFloat(str);

where parseFloat parses its argument, the string str, and attempts to return a floating-point number. If it encounters a character other than a sign (+ or -), a numeral (0-9), a decimal point, or an exponent, then it returns the value up to that point and ignores that character and all succeeding characters. If the first character cannot be converted to a number, it returns "NaN" (not a number).

The syntax of parseInt is:

parseInt(str [, radix]);

parseInt parses its first argument, the string str, and attempts to return an integer of the specified radix (base), indicated by the second, optional argument, radix. For example, a radix of ten indicates to convert to a decimal number, eight octal, sixteen hexadecimal, and so on. For radixes above ten, the letters of the alphabet indicate numerals greater than nine. For example, for hexadecimal numbers (base 16), A through F are used.

If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point. If the first character cannot be converted to a number in the specified radix, it returns "NaN." The parseInt function truncates the string to integer values.

Number and String functions

The Number and String functions let you convert an object to a number or a string. The syntax of these functions is:

var objRef;
objRef = Number(objRef);
objRef = String(objRef);

where objRef is an object reference. Number uses the valueOf() method of the object; String uses the toString() method of the object.

The following example converts the Date object to a readable string.

var D = new Date(430054663215),
    x;
x = String(D); // x equals "Thu Aug 18 04:37:43 GMT-0700 (Pacific Daylight Time) 1983"

The following example converts the String object to Number object.

var str = "12",
    num;
num = Number(str);

You can check it. Use DOM method write() and JavaScript typeof operator.

var str = "12",
    num;
document.write(typeof str);
document.write("<br/>");
num = Number(str);
document.write(typeof num);

escape and unescape functions(Obsoleted above JavaScript 1.5)

The escape and unescape functions do not work properly for non-ASCII characters and have been deprecated. In JavaScript 1.5 and later, use encodeURI, decodeURI, encodeURIComponent, and decodeURIComponent.

The escape and unescape functions let you encode and decode strings. The escape function returns the hexadecimal encoding of an argument in the ISO Latin character set. The unescape function returns the ASCII string for the specified hexadecimal encoding value.

The syntax of these functions is:

escape(string);
unescape(string);

These functions are used primarily with server-side JavaScript to encode and decode name/value pairs in URLs.

Document Tags and Contributors

Contributors to this page: epcode
Última actualización por: epcode,