Como verificar se a função existe em JavaScript?

534

Meu código é

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

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

No entanto, às vezes o meu onChangenão carrega. Erros de Firebug com

me.onChange não é uma função

Eu quero degradar normalmente, porque esse não é o recurso mais importante no meu programa. typeofdá o mesmo erro.

Alguma sugestão de como garantir que ele exista e apenas executar onChange?

(Nenhum dos métodos abaixo, exceto tentar pegar um trabalho)

Alec Smart
fonte
1
@SteveChambers Eu fiz isso. Obrigado por me lembrar.
Alec Smart
pegar a exceção. veja a minha resposta
Matteus Barbosa

Respostas:

1226

Tente algo como isto:

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

ou melhor ainda (de acordo com o comentário acima do UpTheCreek)

if (typeof me.onChange === "function") { 
    // safe to use the function
}
Andrew Hare
fonte
249
=== 'function' seria melhor que! = 'undefined'
UpTheCreek
3
@ James, porque essa declaração realmente lança uma undefinedexceção no JavaScript. Eu tentei.
precisa
8
@UpTheCreek, seria um pouco perigoso como solução geral, já que versões mais antigas do IE tratam certas funções como objetos, por exemplo typeof window.alert === 'object'.
Noyo
1
Por que não usar apenas if (me.onChange) { // do something }?
BornToCode
3
@BornToCode porque então me.onChangepoderia ser qualquer coisa avaliada true, não necessariamente uma função (por exemplo, poderia ser um booleano, uma string, etc.). Por exemplo, consulte jsfiddle.net/j5KAF/1
Ohad Schneider
108

Eu tive esse problema.

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

continuava lançando um erro de referência se obj fosse indefinido.

No final, fiz o seguinte:

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

Um colega me indicou que verificar se é !== 'undefined'e então === 'function'é redundante, é claro.

Mais simples:

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

Muito mais limpo e funciona muito bem.

Misha Nasledov
fonte
1
Alguém tem idéia por que o primeiro trecho de código lança ReferenceError? Isso me parece ilógico.
precisa saber é o seguinte
@saidfagan Veja a definição de ReferenceError developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Misha Nasledov
isso funciona para mim
NewBie1234
1
Qualquer motivo por que typeof obj == 'function' seria insuficiente? ;-) Lembrete: o operador estrito de teste de igualdade só faz sentido quando o operando estático estiver vazio ou nulo ou 0 ou sujeito a qualquer amálgama de conversão como esta.
Fabien Haddadi
16

Se você estiver usando eval para converter uma string em função e quiser verificar se esse método eval'd existe, convém usar typeof e sua string de função dentro de um eval :

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

Não inverter esta e tentar uma typeof em eval . Se você fizer um ReferenceError será lançado:

var functionString = "nonexsitantFunction"
typeof(eval(functionString)) // returns ReferenceError: [function] is not defined
dhulihan
fonte
21
eval == evil;)
Yeti
1
Pode ser ruim, mas isso é muito útil quando o nome da função está em uma variável.
Luke Cousins
8
Você pode fazer isso sem avaliação. Exemplo:var a = 'alert'; window[a]('it works');
zennin
15

E se:

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

por exemplo

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

ou como no seu caso:

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

Veja os documentos MDN .

Nasser Al-Wohaibi
fonte
mas esta solução não está funcionando cada vez :( por exemplo, se eu quero saber que existe lastIndexOf()na string (nós sabemos, que é, mas teoricamente) typeof String().lastIndexOf === "function"é verdade, mas 'lastIndexOf' in Stringé falso.
IIIc
10

Tente typeof- procure 'undefined'dizer que não existe, 'function'para uma função. JSFiddle para este código

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

Ou como um se:

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

Ou com um valor de retorno, em uma única linha:

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

Não vi isso sugerido: me.onChange && me.onChange (str);

Basicamente, se me.onChange estiver indefinido (o que acontecerá se não tiver sido iniciado), ele não executará a última parte. Se me.onChange for uma função, ele executará me.onChange (str).

Você pode ir além e fazer:

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

caso eu também seja assíncrono.

Samir Alajmovic
fonte
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
fonte
sua solução não é clara, pois contém o jQUery, o que é estranho no momento, acho que, por isso, gera erros nos testes simples.
T.Todua
@tazotodua é uma função auto-explicativa. se você deseja usar sem jquery. basta remover a parte &&. essa é uma condição extra para verificar e evitar erros.
Muhammad Tahir
A condição no lado esquerdo da &&conta cuida de algo que o jQuery está isFunctionno lado direito da &&não?
23417 SantiBailors
5

Para mim, a maneira mais fácil:

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}
Tu4n3r
fonte
esta é a resposta correta, porque é uma cadeia de caracteres literais. Eu diria que é melhor assim, if ((typeof window["function_name"] !== 'undefined') && ((typeof window["function_name"] === 'function'))) { return true; } else { return false; }mas é um pequeno ajuste.
Sr. Heelis
4

Vou dar um passo adiante para garantir que a propriedade seja realmente uma função

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

Eu gosto de 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
fonte
3
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

OU

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
fonte
1
Por favor, alguma explicação.
Gufran Hasan
Em dois casos, basta chamar function_exists com o nome do parâmetro function para verificar a existência, retorna bool.
Mohammad Lotfi
3

Coloque o ponto de exclamação duplo, ou seja, !! antes do nome da função que você deseja verificar. Se existir, retornará verdadeiro.

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

Em poucas palavras: pegue a exceção.

Estou realmente surpreso que ninguém tenha respondido ou comentado sobre o Exception Catch neste post ainda.

Detalhe: Aqui vai um exemplo em que tento corresponder a uma função que é prefixada por mask_ e com o sufixo do campo de formulário "name". Quando o JavaScript não encontra a função, ele deve lançar um ReferenceError que você pode manipular como desejar na seção catch.

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
fonte
2

Sem condições

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
fonte
2

Eu suspeitaria que me não está sendo atribuído corretamente o onload.

Mover a chamada get_ID para o evento onclick deve cuidar disso.

Obviamente, você pode prender ainda mais, como mencionado anteriormente:

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

Eu sempre verifico assim:

if(!myFunction){return false;}

basta colocá-lo antes de qualquer código que use essa função

el Dude
fonte
2

Eu tive o caso em que o nome da função variou de acordo com uma variável (var 'x' nesse caso) adicionada ao nome da função. Isso funciona:

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

Este código jQuery simples deve fazer o truque:

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

Eu tentei a resposta aceita; Contudo:

console.log(typeof me.onChange);

retorna 'indefinido'. Notei que a especificação indica um evento chamado 'onchange' em vez de 'onChange' (observe o camelCase).

Alterar a resposta aceita original para a seguinte funcionou para mim:

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

Se você estiver procurando por uma função que seja um plugin jQuery, precisará usar $ .fn.myfunction

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

Eu também tenho procurado uma solução elegante para esse problema. Após muita reflexão, achei melhor essa abordagem.

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

Julian
fonte
Se você estiver procurando pelo minimalizm, também poderá fazer o seguinte: (me.onChange||(_=>_))()Irá executar a função se ela existir, caso contrário não fará nada.
JSideris 22/09/19
É melhor me.onChange && me.onChange()evitar definir uma função nula.
necrifede 27/02
2

Javascript moderno para o resgate!

Isso pode não ter uma grande chance de ser visto com a longa lista de respostas, mas agora isso foi resolvido * no nível do idioma com a nova sintaxe de encadeamento opcional

me.onChange?.(str)

É tão simples assim - onChangesó é chamado se existir .

Se onChangenão existir, nada acontecerá e a expressão retornará undefined- portanto, se ela tiver um valor de retorno que você usaria de outra forma, basta verificar esse valor!== undefined antes de continuar.

Borda caso ressalva - se onChange faz existir, mas é não uma função, você tem uma TypeError. É como você esperaria, é o mesmo que tentar chamar qualquer não-função como uma função, mas vale ressaltar explicitamente que o Encadeamento Opcional não faz mágica para fazer isso desaparecer.

* Bem, tecnicamente, o Opcional Chaining ainda é uma proposta do estágio 4 do TC39, portanto ainda não está na especificação do ECMAScript, mas o estágio 4 significa que ele foi finalizado e sua inclusão é essencialmente garantida, apenas aguardando o lançamento de uma nova versão. Você pode usar a sintaxe em sua versão final hoje via Babel com confiança de que isso não mudará. É mesmo em texto datilografado!

davnicwil
fonte
1

Aqui está uma solução simples e funcional para verificar a existência de uma função e acioná-la dinamicamente por outra função;

Função de gatilho

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
    }
}

e agora você pode gerar a função dinamicamente, talvez usando php como este

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

agora você pode chamar a função usando evento gerado dinamicamente

<?php

$name_frm_somware ="runThis_func";

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

?>

o código HTML exato que você precisa é

<input type="button" value="Button" onclick="runDynamicFunction('runThis_func');">
Aylian Craspa
fonte
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
fonte
0

E depois há isso ...

( document.exitPointerLock || Function )();
Mestre James
fonte
Olá Mestre, bom, mas o que você acha de pegar a Exceção? veja a minha resposta
Matteus Barbosa
Oi obrigado pela nota. Sua solução é admirável. Eu tento evitar o paradigma 'try-catch' sempre que possível ou mais fácil, ou talvez tenha sido implícito / imposto por uma ajuda de terceiros. 'Eval' também é desaprovado por várias razões, uma sendo como tentar pegar outro invólucro, para que o tempo atrase. Existem alternativas para avaliar que também podem ser descartadas. Eu acho que 'nova função (parms, corpo)' pode gerar um erro, mas acho que a próxima pergunta para mim é comparações de velocidade, além da melhor redução de tamanho de código (implica mais rápido para mim). [Hmm, isso parece novo. Eu não tentei jsben.ch]
Master James
Um ponto interessante sobre chamar uma nova função. fique à vontade para enviar sugestões de alterações para minha resposta. muito obrigado
Matteus Barbosa
Sim, quero dizer que mesmo no bash, usando o 'source myScript.sh', você poderá 'exportar' por meio de pseudônimos, etc. Você deve ter um código de verificação do intérprete js se ele não tiver sido sancionado com certeza. Eu criei uma em uma única função, que é outro desafio divertido para ajudar a entender a natureza axiomática mais simples do código, e mesmo um tempo de execução não está além da capacidade de ninguém.
Master James
0

Tente 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;
}

Esteja ciente de que escrevi isso com meu celular. Pode conter alguns problemas em maiúsculas e / ou outras correções necessárias, como por exemplo, nome das funções

Se você deseja uma função como PHP para verificar se o var está definido:

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

Para ilustrar as respostas anteriores, aqui está um trecho rápido do 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_
fonte
0
// just pass your tested function name instead of myFunctionName
if ( $.isFunction($.fn.myFunctionName) ) {
    console.log( 'write your code here.' );
}
Zabid Ahmed
fonte