Как проверить, существует ли функция в JavaScript?


534

Мой код

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

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

Однако иногда мой onChangeне загружается. Ошибки Firebug с

me.onChange не является функцией

Я хочу изящно деградировать, потому что это не самая важная функция в моей программе. typeofвыдает ту же ошибку.

Любые предложения о том, как убедиться, что он существует, а затем только выполнить onChange?

(Ни один из методов ниже, кроме как попробуйте поймать одну работу)


1
@ SteveChambers Я сделал это. Спасибо, что напомнили.
Алек Смарт


поймать исключение.
Маттеус Барбоза

Ответы:


1227

Попробуйте что-то вроде этого:

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

или еще лучше (согласно UpTheCreek Upvoted комментарий)

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

249
=== 'function' будет лучше, чем! = 'undefined'
UpTheCreek,

3
@James, потому что это утверждение на самом деле вызывает undefinedисключение в JavaScript. Я попробовал это.
Майк Перренуд,

8
@UpTheCreek, это было бы немного опасно как общее решение, так как более старые версии IE рассматривают определенные функции как объекты, например typeof window.alert === 'object'.
Noyo

1
Почему бы просто не использовать if (me.onChange) { // do something }?
BornToCode

3
@BornToCode, потому что тогда это me.onChangeможет быть что угодно true, не обязательно функция (например, логическое значение, строка и т. Д.). Например, см. Jsfiddle.net/j5KAF/1
Охад Шнайдер

108

У меня была эта проблема.

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

продолжал выдавать ошибку ссылки, если obj оказался неопределенным.

В итоге я сделал следующее:

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

Коллега указал мне, что проверка, если это, !== 'undefined'а затем, === 'function'является излишним, конечно.

Simpler:

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

Гораздо чище и прекрасно работает.


1
Кто-нибудь имеет представление, почему первый фрагмент кода бросает ReferenceError? Это кажется мне нелогичным.
сказал Фаган

@saidfagan См. определение ReferenceError developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Миша Наследов

это работает для меня
NewBie1234

1
Любой мотив, почему typeof obj == 'function' будет недостаточно? ;-) Напоминание: оператор проверки строгого равенства имеет смысл только тогда, когда статический операнд пуст или равен нулю или равен 0 или подчиняется любой приведенной амальгаме, подобной этой.
Фабьен Хаддади

16

Если вы используете eval для преобразования строки в функцию и хотите проверить, существует ли этот метод eval'd, вам нужно использовать typeof и строку функции внутри eval :

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

Не переворачивайте это и попробуйте typeof на eval . Если вы сделаете ReferenceError будет брошено:

var functionString = "nonexsitantFunction"
typeof(eval(functionString)) // returns ReferenceError: [function] is not defined

21
eval == зло;)
Йети

1
Это может быть плохо, но это очень полезно, когда имя функции находится в переменной.
Люк Кузен

8
Вы можете сделать это без Eval. Пример:var a = 'alert'; window[a]('it works');
zennin

15

Как насчет:

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

например

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

или как для вашего случая:

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

Смотрите MDN документы .


но это решение не работает каждый раз :( например, если я хочу знать, что это есть lastIndexOf()в строке (мы знаем, то есть, но теоретически), typeof String().lastIndexOf === "function"это правда, но 'lastIndexOf' in Stringложно.
IIIC

10

Попробуйте typeof- Ищите, 'undefined'чтобы сказать, что это не существует, 'function'для функции. JSFiddle для этого кода

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

Или как будто:

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

Или с возвращаемым значением в одной строке:

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

9

Не видел это предложил: me.onChange && me.onChange (str);

По сути, если me.onChange не определен (что будет, если он не был инициирован), он не выполнит последнюю часть. Если me.onChange является функцией, она выполнит me.onChange (str).

Вы даже можете пойти дальше и сделать:

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

на случай, если я тоже асинхронен.


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");
    }

Ваше решение не совсем понятно, так как оно содержит jQUery, что, на мой взгляд, странно в данный момент, поэтому оно выдает ошибки при простом тестировании.
Т.Тодуа

@tazotodua это самоочевидная функция. если вы хотите использовать без jquery. просто удалите часть &&. это дополнительное условие, чтобы проверить и избежать ошибок.
Мухаммед Тахир

Соответствует ли условие в левой части объекта тому, &&чего не имеет jQuery isFunctionв правой части &&?
SantiBailors

5

Для меня самый простой способ:

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}

это правильный ответ, потому что это строка буквально .. Я бы сказал, что лучше так, if ((typeof window["function_name"] !== 'undefined') && ((typeof window["function_name"] === 'function'))) { return true; } else { return false; }но это небольшая поправка
мистер Хилис

4

Я сделаю еще один шаг, чтобы убедиться, что свойство действительно является функцией

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


3

Мне нравится использовать этот метод:

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

Применение:

if ( isFunction(me.onChange) ) {
    me.onChange(str); // call the function with params
}


3
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

ИЛИ

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

1
Пожалуйста, объяснение.
Гуфран Хасан

В двух случаях просто вызовите function_exists с именем параметра функции для проверки существования, возвращает bool.
Мохаммад Лотфи

3

Поставь двойной восклицательный знак т.е. перед именем функции, которую вы хотите проверить. Если он существует, он вернет истину.

function abc(){
}
!!window.abc; // return true
!!window.abcd; // return false

3

В нескольких словах: поймать исключение.

Я действительно удивлен, что никто не ответил или прокомментировал Exception Catch в этом посте.

Подробно: здесь приведен пример, в котором я пытаюсь сопоставить функцию с префиксом mask_ и суффиксом поля формы «name». Когда JavaScript не находит функцию, он должен выдать ошибку ReferenceError, которую вы можете обработать по своему усмотрению в секции 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;
    }
  }
}


2

Без условий

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

2

Я подозреваю, что meон не получает правильно назначенную нагрузку.

Перемещение вызова get_ID в событие onclick должно позаботиться об этом.

Очевидно, вы можете в дальнейшем ловушку, как упоминалось ранее:

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

2

Я всегда проверяю так:

if(!myFunction){return false;}

просто поместите его перед любым кодом, который использует эту функцию


2

У меня был случай, когда имя функции менялось в зависимости от переменной (в данном случае var 'x'), добавленной к имени функции. Это работает:

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


2

Я попробовал принятый ответ; Однако:

console.log(typeof me.onChange);

возвращает «неопределенное». Я заметил, что в спецификации указано событие «onchange» вместо «onChange» (обратите внимание на camelCase).

Изменение исходного принятого ответа на следующее работало для меня:

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

2

Если вы проверяете функцию, которая является плагином jQuery, вам нужно использовать $ .fn.myfunction

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

2

Я также искал элегантное решение этой проблемы. После долгих размышлений я нашел этот подход лучше всего.

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


Если вы идете на минимализм, вы также можете сделать это: (me.onChange||(_=>_))()выполнит функцию, если она существует, в противном случае ничего не будет делать.
JSideris

Лучше me.onChange && me.onChange()помешать определить пустую функцию.
necrifede

2

Современный Javascript на помощь!

Это может не иметь большого шанса быть замеченным с длинным списком ответов, но теперь это решается * на уровне языка с новым необязательным синтаксисом цепочки

me.onChange?.(str)

Это так просто - onChangeвызывается, только если он существует .

Если onChangeне существует, ничего не происходит, и выражение возвращается undefined- поэтому, если оно имеет возвращаемое значение, которое вы использовали бы в противном случае, вы можете просто проверить это значение!== undefined прежде чем продолжить.

Предостережение о крайнем случае - если onChange оно существует, но не является функцией, вы получаете TypeError. Как и следовало ожидать, это то же самое, что пытаться вызывать любую не-функцию как функцию, но стоит явно указать, что Optional Chaining не делает никакой магии, чтобы убрать это.

* Ну, технически говоря, Optional Chaining все еще является предложением TC39 4-го этапа, поэтому пока еще не включен в спецификацию ECMAScript, но 4-й этап означает, что он завершен и его включение по существу гарантировано, он просто ожидает поставки новой версии. Вы можете использовать синтаксис в его окончательной версии сегодня через Babel с уверенностью, что он не изменится. Это даже в Typescript!


1

Вот рабочее и простое решение для проверки существования функции и динамического запуска этой функции. другой функцией;

Функция запуска

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

и теперь вы можете генерировать функцию динамически, возможно, с помощью PHP, как это

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

теперь вы можете вызывать функцию, используя динамически генерируемое событие

<?php

$name_frm_somware ="runThis_func";

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

?>

Точный HTML-код вам нужен

<input type="button" value="Button" onclick="runDynamicFunction('runThis_func');">

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

0

И тогда есть это ...

( document.exitPointerLock || Function )();

привет, мастер, хорошо, но что ты думаешь о ловле исключения?
Маттеус Барбоза

Привет спасибо за примечание. Ваше решение достойно восхищения. Я стараюсь избегать парадигмы «попробуй поймать», когда это возможно или проще, или, может быть, это подразумевается / навязывается сторонней помощью. «Eval» также не одобряется по разным причинам, одна из которых похожа на попытку поймать другую обертку, поэтому время затягивается. Есть альтернативы eval, которые тоже могут «скинуть». Я думаю, что «новая функция (parms, body)», возможно, выдаст вам ошибку, но я думаю, что следующий вопрос для меня - сравнение скорости, а не просто лучшее уменьшение размера кода (для меня это означает более быстрое). [Хм, это выглядит новым. Я не пробовал это jsben.ch]
Мастер Джеймс

ммм интересный момент о вызове новой функции вместо этого. не стесняйтесь отправлять свои предложения по изменениям в мой ответ.
Маттеус Барбоза

Я имею в виду, что даже в bash использование «source myScript.sh» позволит вам «экспортировать» с помощью псевдонимов и т. Д. Это похоже на то, что классы и библиотеки всегда были неотъемлемым свойством любого кода. У вас должен быть код проверки интерпретатора js, если он не был санкционирован наверняка. Я построил одну в одной функции, что является еще одной забавной задачей, чтобы помочь понять простейшую аксиоматическую природу кода, и даже время выполнения не выходит за рамки чьих-либо возможностей.
Мастер Джеймс

0

Попробуй это:

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

Имейте в виду, что я написал это на своем мобильном телефоне. Может содержать проблемы с заглавными буквами и / или другие исправления, такие как, например, имя функции.

Если вы хотите, чтобы такая функция, как PHP, проверяла, установлена ​​ли переменная:

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

0

Чтобы проиллюстрировать предыдущие ответы, приведу краткий фрагмент 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
*/


0
// just pass your tested function name instead of myFunctionName
if ( $.isFunction($.fn.myFunctionName) ) {
    console.log( 'write your code here.' );
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.