Проверка, является ли значение функцией - PullRequest
82 голосов
/ 28 апреля 2009

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

РЕДАКТИРОВАТЬ : Конечно, я понимаю, что "return valid ();" это строка У меня есть replace d до «valid ();» и даже «valid ()». Я хочу знать, является ли один из них функцией.

РЕДАКТИРОВАТЬ : Вот код, который может помочь объяснить мою проблему:

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

РЕДАКТИРОВАТЬ 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;
    }
} );

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

Ответы [ 15 ]

78 голосов
/ 28 апреля 2009

Я заменяю кнопку отправки на якорная ссылка. С звонка form.submit () не активируется я нахожу это, и 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>

РЕДАКТИРОВАТЬ: отсутствует параметр f в функции testOnsubmitAndSubmit

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

document.forms['theForm'].onsubmit = onsubmitHandler;
53 голосов
/ 28 апреля 2009

Попробуйте

if (this.onsubmit instanceof Function) {
    // do stuff;
}
12 голосов
/ 28 апреля 2009

Вы можете просто использовать оператор 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 должен решить эту проблему. Хотя я не уверен, работает ли он правильно в нескольких кадрах.

Приветствия

5 голосов
/ 28 апреля 2009

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

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

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

3 голосов
/ 27 апреля 2014

с использованием строковой переменной в качестве примера и использование 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();
}
3 голосов
/ 28 апреля 2009

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

 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.');
 }
3 голосов
/ 28 апреля 2009

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

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

typeof "x"; // returns "string"

typeof x; // returns "function"
2 голосов
/ 28 апреля 2009

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

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

Редактировать (в ответ на ваше второе редактирование):

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

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

2 голосов
/ 28 апреля 2009

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

return SomeFunction(arguments);

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

if (window[functionName]) { 
    // do stuff
}
1 голос
/ 28 апреля 2009

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

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

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

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

$("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()
...