2012-06-14 12 views
11

Considérese el siguiente script:¿Cómo puedo definir condicionalmente una función en javascript?

if (false)​ { 
    function foo() { 
     alert("FOO"); 
    } 
} 
foo(); // alerts "FOO" 

Como se puede ver, la función foo se define y funciona a pesar de que la condición para la if falla.

La razón por la que quiero hacer esto es porque estoy desarrollando una extensión para InDesign y realicé un script llamado utilities.jsx que contiene varias funciones que se utilizan en otros scripts. En todos los scripts que necesitan estas funciones, simplemente uso:

app.doScript(File(scriptsFile.parent.fsName + "/t_utilities.jsx"), ScriptLanguage.JAVASCRIPT); 

que define todas las funciones que necesito y luego puedo usarlas. Ahora, dado que este script será llamado varias veces por varios archivos en un orden impredecible (el usuario decide), pensé que solo podría definir las funciones si no se han definido antes (si utilities.jsx aún no se ha ejecutado) . Algo así como require_once en php.

Estaba pensando en algo así como lo siguiente, pero que no funciona como las funciones se definen cada vez que se ejecuta el script: `

var utilitiesHasRun; 
if (utilitiesHasRun !== true) { 
    // define all the functions 
    // ... 
    utilitiesHasRun = true; 
} 

¿Hay alguna otra opción?

+2

Su primer fragmento de código no es técnicamente válido porque las declaraciones de funciones no están permitidas dentro de los bloques. Solo funciona porque todos los principales navegadores implementan extensiones a la especificación de ECMAScript para tratar este caso. –

+0

Y para continuar @ el comentario de TimDown, su primer fragmento lanzará realmente un SyntaxError si es parte del código de modo estricto. –

Respuesta

6

Para asegurar que su función no se ha definido antes, su uso:

if (typeof yourFunctionName == 'undefined') { 
    yourFunctionName = function(params) { 
    // your code here 
    }; 
} 
+0

Esto arrojará un error si 'yourFunctionName' no está definido inicialmente. Sin embargo, un 'typeof yourFunctionName == 'undefined'' funcionaría. –

+0

@JuanMendes Punto tomado y corregido. – Sirko

15

Puede hacerlos funcionar expresiones en lugar de la función declaraciones:

if (false)​ { 
    var foo = function() { 
     alert("FOO"); 
    }; 
} 
foo(); //TypeError: undefined is not a function 

Tenga en cuenta que en el código anterior, foo sigue siendo accesible a pesar de que la condición evalúa a falso. Esto se debe a que las declaraciones (tanto de función como de variable) se alzan al principio del ámbito en el que se declaran. Sin embargo, las asignaciones suceden en el punto en el código donde aparecen.

Lo que el código está haciendo efectiva es la siguiente:

var foo; //No assignment, foo is undefined 
if (false)​ { 
    foo = function() { 
     alert("FOO"); 
    }; 
} 
foo(); //TypeError: undefined is not a function 

Advertencia - expresiones de funciones con nombre todavía se izan en Internet Explorer 8 y por debajo (esto es un error en IE). Obviamente, este es solo un problema potencial si necesita admitir navegadores antiguos.

+1

+1: muy conciso. No me di cuenta de que las declaraciones de funciones todavía se elevaron, pensé que solo eran expresiones funcionales, ¡pero ahora veo la sutil diferencia! –

+0

+1 Ahh, alzando. Gracias por explicar esto. Elegí la respuesta de Sirko ya que no produce un error, pero su solución también funciona si simplemente pega la llamada a foo ('foo()') en un bloque try, evitando que el error rompa el script. – Shawn

+0

También un error en firefox aparentemente –

3

Puede utilizar los punteros de función para reasignar la función según sea necesario.

var myFunctionPointer = function { alert("Default"); }; 
if (condition) { 
    myFunctionPointer = function { alert("true"); }; 
} 
else { 
    myFunctionPointer = function { alert("false"); }; 
} 
myFunctionPointer(); 
0

Por lo general crear una API completa en base a una función que devuelve un objeto que contiene métodos que son finalmente llamar al menor JS funciones. Las extensiones pueden interactuar con archivos JS con una clase incrustada. Creo que te di el enlace para el libro de cocina.Así que lo que puede hacer es declarar un objeto en AS3 y compruebe si hay alguna propiedad como:

public var jsAPI:Object = {}; 

el código JS sería

var jsAPI = function() { 
    return { 
     hasBeenLoaded:false, 
     myMethod1:function(){}, 
    } 
} 

Entonces, si es necesario utilizar una función JS en AS3, se puede verificar algunos indicadores como:

if (jsAPI.hasBeenLoaded){ … } 
else { //loads the API via new API() } 
Cuestiones relacionadas