¿Cómo verificar si la función existe en JavaScript?

534

Mi código es

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

Sin embargo, a veces mi onChangeno se carga. Errores de Firebug con

me.onChange no es una función

Quiero degradar con gracia porque esta no es la característica más importante en mi programa. typeofda el mismo error.

¿Alguna sugerencia sobre cómo asegurarse de que existe y luego solo ejecutar onChange?

(Ninguno de los métodos a continuación, excepto intentar capturar un trabajo)

Alec Smart
fuente
1
@SteveChambers Lo he hecho. Gracias por recordarme.
Alec Smart
atrapar la excepción. compruebe mi respuesta
Matteus Barbosa

Respuestas:

1227

Intenta algo como esto:

if (typeof me.onChange !== "undefined") { 
    // safe to use the function
}

o mejor aún (según el comentario votado por UpTheCreek)

if (typeof me.onChange === "function") { 
    // safe to use the function
}
Andrew Hare
fuente
249
=== 'función' sería mejor que! = 'undefined'
UpTheCreek
3
@James, porque esa declaración en realidad arroja una undefinedexcepción en el JavaScript. Lo intenté.
Mike Perrenoud
8
@UpTheCreek, sería un poco peligroso como solución general ya que las versiones anteriores de IE tratan ciertas funciones como objetos, por ejemplo typeof window.alert === 'object'.
Noyo
1
¿Por qué no solo usar if (me.onChange) { // do something }?
BornToCode
3
@BornToCode porque me.onChangepodría ser cualquier cosa que se evalúe true, no necesariamente una función (por ejemplo, podría ser un booleano, una cadena, etc.). Por ejemplo, ver jsfiddle.net/j5KAF/1
Ohad Schneider
108

Tuve este problema

if (obj && typeof obj === 'function') { ... }

seguía arrojando un error de referencia si obj no estaba definido.

Al final hice lo siguiente:

if (typeof obj !== 'undefined' && typeof obj === 'function') { ... }

Un colega me señaló que verificar si es !== 'undefined'y luego === 'function'es redundante, por supuesto.

Más simple:

if (typeof obj === 'function') { ... }

Mucho más limpio y funciona muy bien.

Misha Nasledov
fuente
1
¿Alguien tiene idea de por qué arroja el primer fragmento de código ReferenceError? Eso me parece ilógico.
dijo Fagan
@saidfagan Consulte la definición de ReferenceError developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Misha Nasledov el
esto funciona para mí
NewBie1234
1
¿Algún motivo por el cual typeof obj == 'function' sería insuficiente? ;-) Recordatorio: el operador de prueba de igualdad estricta solo tiene sentido cuando el operando estático está vacío o nulo o 0 o sujeto a cualquier amalgama de lanzamiento como esta.
Fabien Haddadi
16

Si está utilizando eval para convertir una cadena en función, y desea verificar si este método evaluado existe, querrá usar typeof y su cadena de función dentro de una evaluación :

var functionString = "nonexsitantFunction"
eval("typeof " + functionString) // returns "undefined" or "function"

No invierta esto e intente un typeof en eval . Si haces un ReferenceError se lanzará:

var functionString = "nonexsitantFunction"
typeof(eval(functionString)) // returns ReferenceError: [function] is not defined
dhulihan
fuente
21
eval == evil;)
Yeti
1
Puede ser malo, pero esto es muy útil cuando el nombre de la función está en una variable.
Luke Cousins ​​el
8
Puede hacer esto sin evaluar. Ejemplo:var a = 'alert'; window[a]('it works');
zennin
15

Qué tal si:

if('functionName' in Obj){
    //code
}

p.ej

var color1 = new String("green");
"length" in color1 // returns true
"indexOf" in color1 // returns true
"blablabla" in color1 // returns false

o en cuanto a su caso:

if('onChange' in me){
    //code
}

Ver documentos de MDN .

Nasser Al-Wohaibi
fuente
pero esta solución no funciona siempre :( por ejemplo, si quiero saber que hay una lastIndexOf()cadena (sabemos, eso es, pero teóricamente) typeof String().lastIndexOf === "function"es verdad, pero 'lastIndexOf' in Stringes falsa.
iiic
10

Intenta typeof: busca 'undefined'decir que no existe, 'function'para una función. JSFiddle para este código

function thisishere() {
    return false;
}
alert("thisishere() is a " + typeof thisishere);
alert("thisisnthere() is " + typeof thisisnthere);

O como si:

if (typeof thisishere === 'function') {
    // function exists
}

O con un valor de retorno, en una sola línea:

var exists = (typeof thisishere === 'function') ? "Value if true" : "Value if false";
var exists = (typeof thisishere === 'function') // Returns true or false
Mat Carlson
fuente
9

No vi esto sugerido: me.onChange && me.onChange (str);

Básicamente, si me.onChange no está definido (lo que será si no se ha iniciado), entonces no ejecutará la última parte. Si me.onChange es una función, me ejecutará.onChange (str).

Incluso puedes ir más allá y hacer:

me && me.onChange && me.onChange(str);

en caso de que yo también sea asíncrono.

Samir Alajmovic
fuente
5
//Simple function that will tell if the function is defined or not
function is_function(func) {
    return typeof window[func] !== 'undefined' && $.isFunction(window[func]);
}

//usage

if (is_function("myFunction") {
        alert("myFunction defined");
    } else {
        alert("myFunction not defined");
    }
Muhammad Tahir
fuente
su solución no está clara, ya que contiene jQUery, lo cual es extraño en este momento, creo, por lo que arroja errores cuando se realizan pruebas simples.
T.Todua
@tazotodua es una función autoexplicativa. si quieres usar sin jquery. simplemente quite la parte &&. Esa es una condición adicional para verificar y evitar errores.
Muhammad Tahir
¿La condición en el lado izquierdo de la &&cuida algo que el jQuery está isFunctionen el lado derecho de la &&no?
SantiBailors
5

Para mí la forma más fácil:

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}
Tu4n3r
fuente
esta es la respuesta correcta, porque es una cadena literal ... Diría que es mejor así, if ((typeof window["function_name"] !== 'undefined') && ((typeof window["function_name"] === 'function'))) { return true; } else { return false; }pero es un ajuste menor
Sr. Heelis
4

Iré un paso más allá para asegurarme de que la propiedad sea realmente una función

function js_to_as( str ){
     if (me && me.onChange && typeof me.onChange === 'function') {
         me.onChange(str);
     }
}
Alex
fuente
3
function js_to_as( str ){
     if (me && me.onChange)
         me.onChange(str);
}
MiffTheFox
fuente
3

Me gusta usar este método:

function isFunction(functionToCheck) {
  var getType = {};
  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}

Uso:

if ( isFunction(me.onChange) ) {
    me.onChange(str); // call the function with params
}
David Douglas
fuente
3
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

O

function function_exists(func_name) {
  //  discuss at: http://phpjs.org/functions/function_exists/
  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Steve Clay
  // improved by: Legaev Andrey
  // improved by: Brett Zamir (http://brett-zamir.me)
  //   example 1: function_exists('isFinite');
  //   returns 1: true

  if (typeof func_name === 'string') {
    func_name = this.window[func_name];
  }
  return typeof func_name === 'function';
}
Mohammad Lotfi
fuente
1
Por favor, alguna explicación.
Gufran Hasan el
En dos casos, simplemente llame a function_exists con el nombre del parámetro de función para verificar la existencia, devuelve bool.
Mohammad Lotfi
3

Poner doble signo de exclamación es decir !! antes del nombre de la función que desea verificar. Si existe, devolverá verdadero.

function abc(){
}
!!window.abc; // return true
!!window.abcd; // return false
Lalnuntluanga Chhakchhuak
fuente
3

En pocas palabras: atrape la excepción.

Estoy realmente sorprendido de que nadie haya respondido o comentado sobre Exception Catch en esta publicación todavía.

Detalle: Aquí hay un ejemplo en el que trato de hacer coincidir una función que tiene el prefijo mask_ y el sufijo del campo de formulario "nombre". Cuando JavaScript no encuentra la función, debe arrojar un ReferenceError que puede manejar como desee en la sección de captura.

function inputMask(input) {
  try {
    let maskedInput = eval("mask_"+input.name);

    if(typeof maskedInput === "undefined")
        return input.value;
    else
        return eval("mask_"+input.name)(input);

  } catch(e) {
    if (e instanceof ReferenceError) {
      return input.value;
    }
  }
}

Matteus Barbosa
fuente
2

Sin condiciones

me.onChange=function(){};

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}
Itay Moav -Malimovka
fuente
2

Sospecho que meno se está asignando correctamente la carga.

Mover la llamada get_ID al evento onclick debería encargarse de ello.

Obviamente, puede atrapar aún más como se mencionó anteriormente:

function js_to_as( str) {
  var me = get_ID('jsExample');
  if (me && me.onChange) {
    me.onChange(str);
  }
}
wombleton
fuente
2

Siempre reviso así:

if(!myFunction){return false;}

simplemente colóquelo antes de cualquier código que use esta función

el tipo
fuente
2

Tuve el caso donde el nombre de la función variaba de acuerdo con una variable (var 'x' en este caso) agregado al nombre de las funciones. Esto funciona:

if ( typeof window['afunction_'+x] === 'function' ) { window['afunction_'+x](); } 
Sebastian H
fuente
2

Este simple código jQuery debería hacer el truco:

if (jQuery.isFunction(functionName)) {
    functionName();
}
mainak chakraborty
fuente
2

He intentado la respuesta aceptada; sin embargo:

console.log(typeof me.onChange);

devuelve 'indefinido'. He notado que la especificación establece un evento llamado 'onchange' en lugar de 'onChange' (observe el camelCase).

Cambiar la respuesta original aceptada a la siguiente funcionó para mí:

if (typeof me.onchange === "function") { 
  // safe to use the function
}
Alexander Fuchs
fuente
2

Si está buscando una función que sea un complemento jQuery, debe usar $ .fn.myfunction

if (typeof $.fn.mask === 'function') {
    $('.zip').mask('00000');
}
Lucas Bustamante
fuente
2

También he estado buscando una solución elegante a este problema. Después de mucha reflexión, encontré este enfoque mejor.

const func = me.onChange || (str => {}); func(str);

Julian
fuente
Si va por minimalizm, también podría hacer esto: (me.onChange||(_=>_))()ejecutará la función si existe, de lo contrario no hará nada.
JSideris
Es mejor me.onChange && me.onChange()evitar definir una función nula.
necrifede
2

¡Javascript moderno al rescate!

Es posible que esto no tenga una gran posibilidad de ser visto con la larga lista de respuestas, pero ahora se resuelve * a nivel de idioma con la nueva sintaxis de encadenamiento opcional

me.onChange?.(str)

Es tan simple como eso: onChangesolo se llama si existe .

Si onChangeno existe, no sucede nada y la expresión regresa undefined, por lo que si tiene un valor de retorno que de lo contrario usaría, simplemente puede verificar este valor !== undefinedantes de continuar.

Edge caso advertencia - si onChange lo hace existe, pero es no una función, se obtiene una TypeError. Esto es lo que cabría esperar, es lo mismo que tratar de llamar a cualquier no función como función, pero vale la pena señalar explícitamente que el Encadenamiento opcional no hace ninguna magia para que esto desaparezca.

* Bueno, técnicamente hablando Opcional Chaining sigue siendo una propuesta de la etapa 4 TC39, por lo que aún no está en la especificación ECMAScript, pero la etapa 4 significa que está finalizada y su inclusión está esencialmente garantizada, solo está esperando que se envíe una nueva versión. Puede usar la sintaxis en su versión final hoy a través de Babel con la confianza de que no cambiará. ¡Incluso en Typecript!

davnicwil
fuente
1

Aquí hay una solución simple y funcional para verificar la existencia de una función y activar otra función dinámicamente ;

Función de disparo

function runDynamicFunction(functionname){ 

    if (typeof window[functionname] == "function") { //check availability

        window[functionname]("this is from the function it"); // run function and pass a parameter to it
    }
}

y ahora puedes generar la función dinámicamente tal vez usando php como este

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

ahora puede llamar a la función usando un evento generado dinámicamente

<?php

$name_frm_somware ="runThis_func";

echo "<input type='button' value='Button' onclick='runDynamicFunction(\"".$name_frm_somware."\");'>";

?>

el código HTML exacto que necesita es

<input type="button" value="Button" onclick="runDynamicFunction('runThis_func');">
Aylian Craspa
fuente
0
    function sum(nb1,nb2){

       return nb1+nb2;
    }

    try{

      if(sum() != undefined){/*test if the function is defined before call it*/

        sum(3,5);               /*once the function is exist you can call it */

      }

    }catch(e){

      console.log("function not defined");/*the function is not defined or does not exists*/
    }
Ir Calif
fuente
0

Y luego está esto...

( document.exitPointerLock || Function )();
Maestro james
fuente
hola Maestro, bueno, pero ¿qué opinas sobre la captura de la excepción? compruebe mi respuesta
Matteus Barbosa
Hola gracias por la nota Tu solución es admirable. Intento evitar el paradigma de 'intentar atrapar' siempre que sea posible o más fácil, o tal vez haya sido implícito / impuesto por una ayuda de terceros. 'Eval' también está mal visto por varias razones, una de ellas es como intentar atrapar a otro contenedor para que se demore el tiempo. Hay alternativas para evaluar que también podrían 'arrojar'. Creo que 'nueva función (parms, body)' podría arrojarle un error, pero supongo que la siguiente pregunta para mí es la comparación de velocidad, aparte de la mejor reducción del tamaño del código (implica más rápido para mí). [Hmm esto parece nuevo. No lo he probado jsben.ch]
Maestro James
mmm rly punto interesante sobre llamar a una nueva función en su lugar. no dude en enviar sus sugerencias de cambios a mi respuesta. muchas gracias
Matteus Barbosa
Sí, quiero decir, incluso en bash, usar 'source myScript.sh' le permitirá 'exportar' a través de alias, etc. Es como si las clases y las bibliotecas siempre hayan sido una propiedad inherente de todos y cada uno de los códigos. Debe tener un código de verificación de intérprete js si no ha sido sancionado con seguridad. Creé uno en una sola función, que es otro desafío divertido para ayudar a comprender la naturaleza axiomática más simple del código, e incluso un tiempo de ejecución no está más allá de la capacidad de nadie.
Maestro James
0

Prueba este:

Window.function_exists=function(function_name,scope){
//Setting default scope of none is provided
If(typeof scope === 'undefined') scope=window;
//Checking if function name is defined
If (typeof function_name === 'undefined') throw new 
Error('You have to provide an valid function name!');
//The type container
var fn= (typeof scope[function_name]);
//Function type
If(fn === 'function') return true;
//Function object type
if(fn.indexOf('function')!== false) return true; 
return false;
}

Tenga en cuenta que he escrito esto con mi teléfono celular. Puede contener algunos problemas en mayúscula y / u otras correcciones necesarias como, por ejemplo, el nombre de las funciones

Si desea que una función como PHP verifique si la var está configurada:

Window.isset=function (variable_con){
If(typeof variable_con !== 'undefined') return true;
return false;
}
SkullWritter
fuente
0

Para ilustrar las respuestas anteriores, aquí hay un fragmento rápido de JSFiddle:

function test () {
console.log()

}

console.log(typeof test) // >> "function"

// implicit test, in javascript if an entity exist it returns implcitly true unless the element value is false as :
// var test = false
if(test){ console.log(true)}
else{console.log(false)}

// test by the typeof method
if( typeof test === "function"){ console.log(true)}
else{console.log(false)}


// confirm that the test is effective : 
// - entity with false value
var test2 = false
if(test2){ console.log(true)}
else{console.log(false)}

// confirm that the test is effective :
// - typeof entity
if( typeof test ==="foo"){ console.log(true)}
else{console.log(false)}

/* Expected :
function
true 
true 
false
false
*/

HoCo_
fuente
0
// just pass your tested function name instead of myFunctionName
if ( $.isFunction($.fn.myFunctionName) ) {
    console.log( 'write your code here.' );
}
Zabid Ahmed
fuente