Тестирование, если значение является функцией

Мне нужно проверить, является ли значение формы onsubmit функцией. Формат обычно onsubmit="return valid();". Есть ли способ узнать, является ли это функцией, и может ли она быть вызванной? Использование typeof просто возвращает, что это строка, которая мне не очень помогает.

EDIT: Конечно, я понимаю, что "return valid();" это строка. У меня replace d до "valid();" и даже "valid()". Я хочу знать, является ли любая из них функцией.

EDIT. Здесь приведен код, который может помочь объяснить мою проблему:

$("a.button").parents("form").submit(function() {
    var submit_function = $("a.button").parents("form").attr("onsubmit");
    if ( submit_function && typeof( submit_function.replace(/return /,"") ) == 'function' ) {
        return eval(submit_function.replace(/return /,""));
    } else {
        alert("onSubmit is not a function.\n\nIs the script included?"); return false;
    }
} );

EDIT 2: здесь новый код. Кажется, что мне все еще нужно использовать eval, потому что вызывающий form.submit() не запускает существующие onsubmits.

var formObj = $("a.button").parents("form");
formObj.submit(function() {
    if ( formObj[0].onsubmit && typeof( formObj.onsubmit ) == 'function' ) {
        return eval(formObj.attr("onsubmit").replace(/return /,""));
    } else {
        alert("onSubmit is not a function.\n\nIs the script included?");
        return false;
    }
} );

Предложения о возможностях, как это сделать лучше?

Ответы

Ответ 1

Я заменяю кнопку отправки кнопкой якорная связь. Поскольку вызов form.submit() не активирует onsubmit's, я нахожу это, и eval() сам. Но я бы хотел проверьте, существует ли функция до просто eval(), что там. - gms8994

<script type="text/javascript">
function onsubmitHandler() {
    alert('running onsubmit handler');
    return true;
}
function testOnsubmitAndSubmit(f) {
    if (typeof f.onsubmit === 'function') {
        // onsubmit is executable, test the return value
        if (f.onsubmit()) {
            // onsubmit returns true, submit the form
            f.submit();
        }
    }
}
</script>

<form name="theForm" onsubmit="return onsubmitHandler();">
<a href="#" onclick="
    testOnsubmitAndSubmit(document.forms['theForm']);
    return false;
"></a>
</form>

EDIT: отсутствует параметр f в функции testOnsubmitAndSubmit

Вышеуказанное должно работать независимо от того, присваиваете ли вы атрибут onsubmit HTML или назначаете его в JavaScript:

document.forms['theForm'].onsubmit = onsubmitHandler;

Ответ 2

Попробуйте

if (this.onsubmit instanceof Function) {
    // do stuff;
}

Ответ 3

Вы можете просто использовать оператор typeof вместе с тройным оператором:

onsubmit="return typeof valid =='function' ? valid() : true;"

Если это функция, мы вызываем ее и возвращаем возвращаемое значение, иначе просто возвращаем true

Edit:

Я не совсем уверен, что вы действительно хотите сделать, но я попытаюсь объяснить, что может произойти.

Когда вы объявляете свой код onsubmit в своем html, он превращается в функцию и, следовательно, ее можно вызывать из "мира" JavaScript. Это означает, что эти два метода эквивалентны:

HTML: <form onsubmit="return valid();" />
JavaScript: myForm.onsubmit = function() { return valid(); };

Эти два будут обеим функциями, и оба будут вызываемыми. Вы можете протестировать любой из тех, кто использует оператор typeof, который должен сгладить тот же результат: "function".

Теперь, если вы присвоите строку свойству onsubmit через JavaScript, она останется строкой, поэтому не будет использоваться. Обратите внимание, что если вы примените к нему оператор typeof, вы получите "string" вместо "function".

Надеюсь, это может прояснить некоторые вещи. Опять же, если вы хотите знать, является ли такое свойство (или любой идентификатор для этого вопроса) функцией и вызываемой, оператор typeof должен сделать трюк. Хотя я не уверен, правильно ли он работает на нескольких кадрах.

Приветствия

Ответ 4

Какой браузер вы используете?

alert(typeof document.getElementById('myform').onsubmit);

Это дает мне "function" в IE7 и FireFox.

Ответ 5

Убедитесь, что вы вызываете typeof для текущей функции, а не для строкового литерала:

function x() { 
    console.log("hi"); 
}

typeof "x"; // returns "string"

typeof x; // returns "function"

Ответ 6

Вы можете попробовать изменить эту технику в соответствии с вашими потребностями:

 function isFunction() {
   var functionName = window.prompt('Function name: ');
   var isDefined = eval('(typeof ' + functionName + '==\'function\');');
   if (isDefined)
     eval(functionName + '();');
   else
     alert('Function ' + functionName + ' does not exist');
 }
 function anotherFunction() {
   alert('message from another function.');
 }

Ответ 7

Если это строка, вы можете предположить/надеяться, что она всегда имеет форму

return SomeFunction(arguments);

проанализируйте имя функции, а затем посмотрите, определена ли эта функция с помощью

if (window[functionName]) { 
    // do stuff
}

Ответ 8

form.submit всегда будет функцией, определяемой как атрибут HTML, элементом формы. Это некоторая анонимная функция, прикрепленная к элементу HTML, которая имеет этот указатель, связанный с этим элементом FORM, а также имеет параметр с именем event, который будет содержать данные о событии отправки.

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

Изменить (как ответ на второе редактирование):

Я считаю, что обработчик, прикрепленный к атрибуту HTML, будет выполняться независимо от вышеуказанного кода. Более того, вы можете как-то остановить его, но, похоже, что FF 3, IE 8, Chrome 2 и Opera 9 в первую очередь выполняют обработчик атрибутов HTML, а затем тот, который был прикреплен (я не тестировал с помощью jQuery хотя, с addEventListener и attachEvent). Итак... что вы пытаетесь выполнить точно?

Кстати, ваш код не работает, потому что ваше регулярное выражение будет извлекать строку "valid();", что определенно не является функцией.

Ответ 9

Ну, "return valid();" - это строка, поэтому правильно.

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

formId.onsubmit = function (){ /* */ }

if(typeof formId.onsubmit == "function"){
  alert("it a function!");
}

Ответ 10

  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }

Ответ 11

Я думаю, что источником путаницы является различие между атрибутом node и соответствующим свойством.

Вы используете:

$("a.button").parents("form").attr("onsubmit")

Вы прямо читаете значение onsubmit атрибута (которое должно быть строкой). Вместо этого вы должны получить доступ к свойству onsubmit node:

$("a.button").parents("form").prop("onsubmit")

Вот быстрый тест:

<form id="form1" action="foo1.htm" onsubmit="return valid()"></form>
<script>
window.onload = function () {
    var form1 = document.getElementById("form1");

    function log(s) {
        document.write("<div>" + s + "</div>");
    }

    function info(v) {
        return "(" + typeof v + ") " + v;
    }

    log("form1 onsubmit property: " + info(form1.onsubmit));
    log("form1 onsubmit attribute: " + info(form1.getAttribute("onsubmit")));
};
</script> 

Это дает:

form1 onsubmit property: (function) function onsubmit(event) { return valid(); }
form1 onsubmit attribute: (string) return valid()

Ответ 12

Вы всегда можете использовать одну из функций typeOf в блогах JavaScript, таких как Chris West. Использование определения, например следующего для функции typeOf(), будет работать:

function typeOf(o){return {}.toString.call(o).slice(8,-1)}

Эта функция (объявленная в глобальном пространстве имен) может быть использована следующим образом:

alert("onsubmit is a " + typeOf(elem.onsubmit));

Если это функция, возвращается функция "Функция". Если это строка, возвращается "String". Другие возможные значения показаны здесь.

Ответ 13

// This should be a function, because in certain JavaScript engines (V8, for
// example, try block kills many optimizations).
function isFunction(func) {
    // For some reason, function constructor doesn't accept anonymous functions.
    // Also, this check finds callable objects that aren't function (such as,
    // regular expressions in old WebKit versions), as according to EcmaScript
    // specification, any callable object should have typeof set to function.
    if (typeof func === 'function')
        return true

    // If the function isn't a string, it probably good idea to return false,
    // as eval cannot process values that aren't strings.
    if (typeof func !== 'string')
        return false

    // So, the value is a string. Try creating a function, in order to detect
    // syntax error.
    try {
        // Create a function with string func, in order to detect whatever it's
        // an actual function. Unlike examples with eval, it should be actually
        // safe to use with any string (provided you don't call returned value).
        Function(func)
        return true
    }
    catch (e) {
        // While usually only SyntaxError could be thrown (unless somebody
        // modified definition of something used in this function, like
        // SyntaxError or Function, it better to prepare for unexpected.
        if (!(e instanceof SyntaxError)) {
            throw e
        }

        return false
    }
}

Ответ 14

с использованием строковой переменной в качестве примера и использования instanceof Function Вы регистрируете функцию... присваиваете переменную... проверьте переменную - это имя функции... выполните предварительную обработку... назначьте функцию новому var... затем вызовите функцию.

function callMe(){
   alert('You rang?');
}

var value = 'callMe';

if (window[value] instanceof Function) { 
    // do pre-process stuff
    // FYI the function has not actually been called yet
    console.log('callable function');
    //now call function
   var fn = window[value];
   fn();
}

Ответ 15

Простая проверка, как это, даст вам знать, существует ли она/определена:

if (this.onsubmit)
{
  // do stuff;
}