Kiểm tra xem giá trị có phải là một hàm không


88

Tôi cần kiểm tra xem giá trị của biểu mẫu có phải onsubmitlà một hàm hay không. Định dạng thường là onsubmit="return valid();". Có cách nào để biết đây có phải là một hàm hay không và nó có thể gọi được không? Sử dụng typeof chỉ trả về rằng đó là một chuỗi, điều này không giúp tôi nhiều.

CHỈNH SỬA : Tất nhiên, tôi hiểu rằng "return valid ();" là một chuỗi. Tôi đã đặt replacenó xuống thành "valid ();", và thậm chí là "valid ()". Tôi muốn biết nếu một trong hai cái đó là một hàm.

CHỈNH SỬA : Đây là một số mã, có thể giúp giải thích sự cố của tôi:

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

CHỈNH SỬA 2 : Đây là mã mới. Có vẻ như tôi vẫn phải sử dụng eval, vì việc gọi form.submit () không kích hoạt các tệp gửi đến hiện có.

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

Đề xuất về cách có thể làm điều này tốt hơn?

Câu trả lời:


85

Tôi đang thay thế nút gửi bằng một liên kết cố định. Vì việc gọi form.submit () không kích hoạt onsubmit, tôi đang tìm nó và tự đánh giá () ing nó. Nhưng tôi muốn kiểm tra xem hàm có tồn tại hay không trước khi chỉ eval () ing những gì ở đó. - 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>

CHỈNH SỬA: thiếu tham số f trong kiểm tra chức năngOnsubmitAndSubmit

Ở trên sẽ hoạt động bất kể bạn gán onsubmitthuộc tính HTML hay gán nó trong JavaScript:

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

1
f trong f.onsubmit đến từ đâu?
nghệ

flà một thể hiện biểu mẫu. Bạn chuyển nó vào hàm testOnsubmitAndSubmit làm đối số. (Tôi biết câu hỏi này khá cũ, nhưng có lẽ câu trả lời của tôi sẽ giúp ai đó tiết kiệm thời gian :))
zeroos

63

Thử

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

7
đó chỉ là một mẫu. Bạn có thể thay đổi nó để button.onsubmit instanceof Chức năng
artemb

13

Bạn chỉ cần sử dụng typeoftoán tử cùng với toán tử bậc ba viết tắt:

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

Nếu nó là một hàm, chúng tôi gọi nó và trả về giá trị trả về của nó, nếu không, chỉ cần trả về true

Biên tập:

Tôi không chắc bạn thực sự muốn làm gì, nhưng tôi sẽ cố gắng giải thích những gì có thể đang xảy ra.

Khi bạn khai báo onsubmitmã của mình trong html, nó sẽ được chuyển thành một hàm và do đó nó có thể được gọi từ "thế giới" JavaScript. Điều đó có nghĩa là hai phương pháp đó là tương đương:

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

Hai cái này sẽ là cả hai hàm và cả hai đều có thể gọi được. Bạn có thể kiểm tra bất kỳ của những người sử dụng các typeoftoán tử mà nên không có sữa cùng một kết quả: "function".

Bây giờ nếu bạn gán một chuỗi cho thuộc tính "gửi đi" qua JavaScript, nó sẽ vẫn là một chuỗi, do đó không thể gọi được. Lưu ý rằng nếu bạn áp dụng typeoftoán tử chống lại nó, bạn sẽ nhận được "string"thay vì "function".

Tôi hy vọng điều này có thể làm rõ một vài điều. Sau đó, một lần nữa, nếu bạn muốn biết liệu thuộc tính đó (hoặc bất kỳ số nhận dạng nào cho vấn đề) là một hàm và có thể gọi hay không, typeofnhà điều hành nên thực hiện thủ thuật. Mặc dù tôi không chắc liệu nó có hoạt động bình thường trên nhiều khung hình hay không.

Chúc mừng


Tôi cần phải kiểm tra điều này bên ngoài gửi đến.
Glen Solsberry

5

Bạn đang dùng trình duyệt nào?

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

Điều này mang lại cho tôi " function" trong IE7 và FireFox.


Ngay cả khi thư gửi của bạn là "return valid ();"?
Glen Solsberry

1
Có - đừng quên, bạn không thể có "return" bên ngoài một hàm.
Greg

form.onsubmit sẽ luôn là một hàm miễn là nó được định nghĩa là một thuộc tính HTML. Hãy xem câu trả lời của tôi.
Ionuț G. Stan

4

sử dụng biến dựa trên chuỗi làm ví dụ và sử dụng instanceof Function Bạn đăng ký hàm.. gán biến ... kiểm tra biến là tên của hàm ... thực hiện tiền xử lý ... gán hàm cho new var ... sau đó gọi hàm.

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
Bạn không thực sự cần biến fn đó, bạn chỉ có thể sử dụng window [value] ();
Lajos Meszaros

1
yea Tôi biết nhưng tôi cũng nhận ra rằng nó thường là dễ hiểu trong một định dạng dài và vì đây là chủ yếu một trang web cho việc học đầu vào của bạn có giá trị trong bất kỳ trường hợp @LajosMeszaros
CrandellWS

3

Đảm bảo rằng bạn đang gọi typeof trên hàm thực, không phải là một chuỗi ký tự:

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

typeof "x"; // returns "string"

typeof x; // returns "function"

3

Bạn có thể thử sửa đổi kỹ thuật này cho phù hợp với nhu cầu của mình:

 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 sẽ luôn là một hàm khi được định nghĩa là một thuộc tính của HTML phần tử biểu mẫu. Đó là một số loại hàm ẩn danh được gắn với một phần tử HTML, có con trỏ này liên kết với phần tử FORM đó và cũng có một tham số được đặt tên eventsẽ chứa dữ liệu về sự kiện gửi.

Trong những trường hợp này, tôi không hiểu làm thế nào bạn có một chuỗi là kết quả của một phép toán kiểu. Bạn nên cung cấp thêm chi tiết, tốt hơn một số mã.

Chỉnh sửa (như một phản hồi cho lần chỉnh sửa thứ hai của bạn):

Tôi tin rằng trình xử lý được đính kèm với thuộc tính HTML sẽ thực thi bất kể mã ở trên. Hơn nữa, bạn có thể cố gắng ngăn chặn bằng cách nào đó, nhưng có vẻ như FF 3, IE 8, Chrome 2 và Opera 9 đang thực thi trình xử lý thuộc tính HTML ngay từ đầu và sau đó là trình xử lý được đính kèm (tôi đã không thử nghiệm với jQuery mặc dù, nhưng với addEventListener và attachmentEvent). Vậy ... chính xác thì bạn đang cố gắng hoàn thành điều gì?

Nhân tiện, mã của bạn không hoạt động vì biểu thức chính quy của bạn sẽ trích xuất chuỗi "valid ();", chắc chắn không phải là một hàm.


2

Nếu đó là một chuỗi, bạn có thể giả định / hy vọng nó luôn ở dạng

return SomeFunction(arguments);

phân tích cú pháp cho tên hàm, sau đó xem liệu hàm đó có được định nghĩa bằng cách sử dụng

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

tôi đã muốn thêm độ phân giải này cũng ... chỉ cần nhớ để đăng ký chức năng ở cấp tài liệu / cửa sổ
CrandellWS

1

Vâng, "return valid();" một chuỗi, vì vậy điều đó chính xác.

Nếu bạn muốn kiểm tra xem nó có một chức năng được đính kèm hay không, bạn có thể thử cách này:

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

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

1

Tôi nghĩ rằng nguồn gốc của sự nhầm lẫn là sự phân biệt giữa một nút thuộc tính và tương ứng với tài sản .

Bạn đang sử dụng:

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

Bạn đang đọc trực tiếp giá trị của onsubmit thuộc tính ( phải là một chuỗi). Thay vào đó, bạn nên truy cập thuộc onsubmit tính của nút:

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

Đây là một bài kiểm tra nhanh:

<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> 

Điều này mang lại:

Thuộc tính onsubmit form1: (function) function onsubmit (event) {return valid (); }
Thuộc tính gửi qua form1: (string) return valid ()

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

1

Không phải typeof xxx === 'function'là tốt nhất và nhanh nhất?

Tôi đã làm một băng ghế dự bị mà bạn có thể thử nó, so với instanceof và _underscore

  1. Nó chỉ có vẻ nhanh hơn instanceof (sử dụng chrome)
  2. Sẽ không xảy ra lỗi nếu biến không được xác định

Đây là một chiếc ghế dài: https://jsbench.me/qnkf076cqb/1


0

Bạn luôn có thể sử dụng một trong các hàm typeOf trên các blog JavaScript chẳng hạn như của Chris West . Sử dụng một định nghĩa như sau cho typeOf()hàm sẽ hoạt động:

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

Hàm này (được khai báo trong không gian tên chung, có thể được sử dụng như sau:

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

Nếu đó là một hàm, "Hàm" sẽ được trả về. Nếu đó là một chuỗi, "Chuỗi" sẽ được trả về. Các giá trị có thể khác được hiển thị ở đây .


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

Một kiểm tra đơn giản như thế này sẽ cho bạn biết nếu nó tồn tại / được định nghĩa:

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

6
Điều này sẽ không hoạt động. Nếu sẽ khẳng định là TRUE khi gửi đi cũng là một chuỗi không trống.
Seb

1
Một cách kiểm tra khủng khiếp nếu một cái gì đó là một chức năng - như đã chỉ ra, và rõ ràng hơn: bất kỳ điều gì "trung thực" sẽ khiến mã này "làm được" và đó có thể không phải là những gì được mong đợi. Nếu this.onsubmit được đặt thành giá trị 5 hoặc "hello" hoặc bất kỳ thứ gì khác trong JavaScript đánh giá là true, bạn sẽ nhận được hành vi không mong muốn.
Jason Bunting

Chủ đề của câu hỏi yêu cầu làm thế nào để kiểm tra xem có thứ gì đó tồn tại hay không. Đó là tất cả những gì tôi gợi ý - không hơn, không kém.
Kon

Không hẳn - người đăng ban đầu nói rằng anh ta có "nhu cầu kiểm tra xem giá trị của một biểu mẫu gửi đi có phải là một hàm hay không." Tình trạng của bạn không phải là có hay không this.onsubmit là một funciton, thử nghiệm của bạn chỉ đơn giản là yêu cầu hay không this.onsubmit là "truthy"
Jason Bunting
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.