97

我需要测试一个表单的值是否onsubmit是一个函数。格式通常为onsubmit="return valid();". 有没有办法判断这是否是一个函数,以及它是否可调用?使用 typeof 只是返回它是一个字符串,这对我没有多大帮助。

编辑:当然,我理解“返回有效();” 是一个字符串。我把replace它归结为“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;
    }
} );

关于如何更好地做到这一点的建议?

4

18 回答 18

93

我正在用锚链接替换提交按钮。由于调用 form.submit() 不会激活 onsubmit 的,我正在找到它,并自己评估它。但我想在 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>

编辑:函数 testOnsubmitAndSubmit 中缺少参数 f

无论您是分配onsubmitHTML 属性还是在 JavaScript 中分配它,上述内容都应该有效:

document.forms['theForm'].onsubmit = onsubmitHandler;
于 2009-04-28T18:48:20.037 回答
69

尝试

if (this.onsubmit instanceof Function) {
    // do stuff;
}
于 2009-04-28T14:50:05.210 回答
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应该产生相同结果的运算符来测试任何一个:"function".

现在,如果您通过 JavaScript 将字符串分配给“onsubmit”属性,它将保持为字符串,因此不可调用。请注意,如果您typeof对它应用运算符,您将得到"string"而不是"function".

我希望这可以澄清一些事情。再说一次,如果你想知道这样的属性(或任何标识符)是否是一个函数并且是可调用的,那么typeof操作员应该可以做到这一点。虽然我不确定它是否可以在多个帧上正常工作。

干杯

于 2009-04-28T15:17:00.603 回答
5

你使用的是什么浏览器?

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

这给了我function在 IE7 和 FireFox 中的“”。

于 2009-04-28T14:49:00.483 回答
4

使用基于字符串的变量作为示例并使用 instanceof Function 您注册函数..分配变量...检查变量是函数的名称...进行预处理...将函数分配给新变量...然后调用函数。

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();
}
于 2014-04-26T22:24:55.277 回答
3

确保您在实际函数上调用 typeof,而不是字符串文字:

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

typeof "x"; // returns "string"

typeof x; // returns "function"
于 2009-04-28T14:48:51.483 回答
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.');
 }
于 2009-04-28T14:49:48.517 回答
2

如果它是一个字符串,你可以假设/希望它总是形式

return SomeFunction(arguments);

解析函数名称,然后查看该函数是否使用

if (window[functionName]) { 
    // do stuff
}
于 2009-04-28T14:52:45.937 回答
2

form.onsubmit 在定义为 HTML 表单元素的属性时将始终是一个函数。它是附加到 HTML 元素的某种匿名函数,它的this指针绑定到该 FORM 元素,并且还有一个名为的参数,该参数event将包含有关提交事件的数据。

在这些情况下,我不明白您是如何通过 typeof 操作获得字符串的。你应该提供更多细节,更好的一些代码。

编辑(作为对您的第二次编辑的回应):

我相信无论上面的代码如何,附加到 HTML 属性的处理程序都会执行。此外,您可以尝试以某种方式停止它,但是,FF 3、IE 8、Chrome 2 和 Opera 9 似乎首先执行 HTML 属性处理程序,然后执行附加的处理程序(我没有使用 jQuery 进行测试虽然,但使用 addEventListener 和 attachEvent)。那么......你到底想完成什么?

顺便说一句,您的代码不起作用,因为您的正则表达式将提取字符串“valid();”,这绝对不是一个函数。

于 2009-04-28T17:32:20.170 回答
2

不是typeof xxx === 'function'最好的和最快的吗?

与 instanceof 和 _underscore 相比,我做了一个长凳,您可以尝试一下

  1. 它似乎比 instanceof 更快(使用 chrome)
  2. 如果未定义变量,它不会引发错误

这里有一张长凳:https ://jsbench.me/qnkf076cqb/1

于 2020-09-12T21:51:47.533 回答
1

嗯,"return valid();" 一个字符串,所以这是正确的。

如果你想检查它是否附加了一个函数,你可以试试这个:

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

if(typeof formId.onsubmit == "function"){
  alert("it's a function!");
}
于 2009-04-28T14:50:22.213 回答
1
  if ( window.onsubmit ) {
     //
  } else {
     alert("Function does not exist.");
  }
于 2009-04-28T14:53:16.887 回答
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 属性:(function) function onsubmit(event) { return valid(); }
form1 onsubmit 属性:(字符串)返回有效()
于 2009-04-28T18:46:21.617 回答
1

您始终可以在 JavaScript 博客(例如Chris West 的. 对函数使用如下定义typeOf()会起作用:

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

这个函数(在全局命名空间中声明,可以这样使用:

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

如果是函数,则返回“Function”。如果是字符串,则返回“String”。此处显示了其他可能的值。

于 2012-07-03T17:42:28.147 回答
1
// 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
    }
}
于 2013-08-31T08:28:34.427 回答
1

注意 es6 类也是一个函数但不可调用

class C {}

typeof C === "function"  // true
C instanceof Function    // true

C()       // error
C.call()  // error
new C()   // okay
new C     // okay
于 2021-07-23T15:14:07.633 回答
1

检查call值的方法似乎是一个足够好的测试。例如,val.call && val()

> a = () => {}
[Function: a]
> function b() {}
undefined
> c = function(){}
  [Function: c]
> d = 2
2
> e = []
  []
> f = {}
{}
> a.call
  [Function: call]
> b.call
  [Function: call]
> c.call
  [Function: call]
> d.call
undefined
> e.call
undefined
> f.call
undefined

注意:除非是上课。

于 2021-10-04T10:40:33.983 回答
-3

像这样的简单检查会让您知道它是否存在/已定义:

if (this.onsubmit)
{
  // do stuff;
}
于 2009-04-28T14:47:16.823 回答