Перевірка, чи значення є функцією


88

Мені потрібно перевірити, чи є значення форми onsubmitфункцією. Формат зазвичай onsubmit="return valid();". Чи є спосіб визначити, чи є це функцією, і чи можна її викликати? Використання typeof просто повертає, що це рядок, що мені не надто допомагає.

EDIT : Звичайно, я розумію, що "return valid ();" є рядком. Я replaceзвів це до "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;
    }
} );

Пропозиції щодо того, як зробити це краще?

Відповіді:


85

Я замінюю кнопку надсилання на прив’язне посилання. Оскільки виклик 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;

1
звідки походить f у f.onsubmit?
Art

fє екземпляром форми. Ви передаєте його функції testOnsubmitAndSubmit як аргумент. (Я знаю, що це запитання досить давнє, але, можливо, моя відповідь заощадить комусь час :))
zeroos

63

Спробуйте

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

7
це лише зразок. Ви можете змінити його на button.onsubmit instanceof Function
artemb

13

Ви можете просто скористатися typeofоператором разом із потрійним оператором:

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

Якщо це функція, ми викликаємо її і повертаємо її повернене значення, інакше просто повертаємо true

Редагувати:

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

Коли ви оголошуєте свій onsubmitкод у своєму html, він перетворюється на функцію і, отже, її можна викликати з "світу" JavaScript. Це означає, що ці два методи еквівалентні:

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

Ці дві функції будуть обома функціями, і обидві їх можна викликати. Ви можете протестувати будь-який з тих , хто використовує typeofоператор , який повинен yeld той же результат: "function".

Тепер, якщо ви призначите рядок властивості "onsubmit" через JavaScript, він залишиться рядком, отже, не викликається. Зверніть увагу, що якщо ви застосуєте typeofоператор проти нього, ви отримаєте "string"замість "function".

Сподіваюся, це може пояснити кілька речей. Знову ж таки, якщо ви хочете дізнатись, чи така властивість (або будь-який ідентифікатор справи) є функцією та викликається, typeofоператор повинен зробити це. Хоча я не впевнений, чи працює він належним чином у кількох кадрах.

Ура


Мені потрібно протестувати це за межами onsubmit.
Glen Solsberry

5

Який браузер ви використовуєте?

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

Це дає мені " function" в IE7 та FireFox.


Навіть якщо ваш onsubmit має значення "return valid ();"?
Glen Solsberry

1
Так - не забувайте, ви не можете мати "повернення" поза функцією.
Грег

form.onsubmit завжди буде функцією, якщо вона визначена як атрибут HTML. Дивіться мою відповідь.
Ionuț G. Stan

4

використовуючи на прикладі змінну на основі рядка та використовуючи 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();
}

2
Вам насправді не потрібна ця змінна fn, ви можете просто використовувати window [value] ();
Лайош Месарос

1
да я знаю , але я також розумію , що це , як правило , легше зрозуміти , в довгому форматі , як це перш за все місце для навчання вашого вкладу цінується в будь-якому випадку @LajosMeszaros
CrandellWS

3

Переконайтеся, що ви викликаєте typeof для фактичної функції, а не рядкового літералу:

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

typeof "x"; // returns "string"

typeof x; // returns "function"

3

Ви можете спробувати змінити цю техніку відповідно до своїх потреб:

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

2

form.onsubmit завжди буде функцією, коли вона визначається як атрибут HTML елемента форми. Це якась анонімна функція, приєднана до елемента HTML, яка має цей покажчик, прив’язаний до цього елемента FORM, а також має параметр з іменем, eventякий буде містити дані про подію подання.

За цих обставин я не розумію, як ви отримали рядок в результаті операції typeof. Ви повинні надати більше деталей, краще якийсь код.

Редагувати (як відповідь на ваше друге редагування):

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

До речі, ваш код не працює, оскільки ваш регулярний вираз витягне рядок "valid ();", що точно не є функцією.


2

Якщо це рядок, ви можете припустити / сподіватися, що він завжди має форму

return SomeFunction(arguments);

проаналізуйте ім'я функції, а потім перевірте, чи визначена ця функція за допомогою

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

я збирався також додати цю роздільну здатність ... просто не забудьте зареєструвати функцію на рівні документа / вікна
CrandellWS

1

Ну, "return valid();" це рядок, тож це правильно.

Якщо ви хочете перевірити, чи замість нього приєднана функція, ви можете спробувати це:

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

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

1

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

Ви використовуєте:

$("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 властивість: (функція) функція onsubmit (подія) {return valid (); }
атрибут onsubmit form1: (рядок) повернення дійсного ()


1

Хіба не typeof xxx === 'function'найкращий і найшвидший?

Я зробив стенд, на якому ви можете спробувати, порівняно з instanceof та _underscore

  1. Це, здається, швидше, ніж instanceof (за допомогою хрому)
  2. Це не призведе до помилки, якщо змінна не визначена

Ось лавка: https://jsbench.me/qnkf076cqb/1


0

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

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

Цю функцію (яка оголошена в глобальному просторі імен, можна використовувати так:

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

Якщо це функція, буде повернено "Функція". Якщо це рядок, буде повернено "Рядок". Інші можливі значення показані тут .


0
// 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's 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's better to prepare for unexpected.
        if (!(e instanceof SyntaxError)) {
            throw e
        }

        return false
    }
}

-3

Така проста перевірка дасть вам знати, чи існує вона / визначена:

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

6
Це не спрацює. Якщо if буде стверджувати TRUE, коли onsubmit також є непустим рядком.
Себ

1
Жахливий спосіб тестування, якщо щось є функцією - як зазначено, і щоб бути зрозумілішим: будь-що "хитке" призведе до того, що цей код "робитиме речі", і це може бути не те, що очікується. Якщо для this.onsubmit було встановлено значення 5 або "привіт" або щось інше в JavaScript, яке вважає істинним, ви отримаєте несподівану поведінку.
Джейсон Бантінг,

Тема запитання запитує, як перевірити, чи щось існує. Це все, що я пропонував - ні більше, ні менше.
Kon

Не зовсім так - оригінал опублікованого стверджує, що йому потрібно "перевірити, чи є значення onsubmit форми функцією". Ваша умова полягає не в тому, чи є this.onsubmit функціональним, ваш тест просто запитує, чи є this.onsubmit "неправдивим"
Джейсон Бантінг,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.