Тестирование, если значение является функцией
Мне нужно проверить, является ли значение формы 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;
}