Değerin bir işlev olup olmadığını test etme


88

Bir formun değerinin onsubmitbir fonksiyon olup olmadığını test etmem gerekiyor . Biçim tipiktir onsubmit="return valid();". Bunun bir işlev olup olmadığını ve çağrılabilir olup olmadığını anlamanın bir yolu var mı? Typeof kullanmak sadece bir dizge olduğunu döndürür ki bu bana pek yardımcı olmaz.

DÜZENLEME : Tabii ki, "return valid ();" bir dizedir. Bunu replace"geçerli ();" ve hatta "geçerli ()" olarak belirledim. Bunlardan herhangi birinin bir işlev olup olmadığını bilmek istiyorum.

DÜZENLEME : Sorunumu açıklamaya yardımcı olabilecek bazı kodlar:

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

DÜZENLEME 2 : İşte yeni kod. Görünüşe göre hala bir eval kullanmam gerekiyor, çünkü form.submit () 'i çağırmak mevcut onsubmits'i tetiklemiyor.

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

Bunun nasıl daha iyi yapılacağına dair öneriler?

Yanıtlar:


85

Gönder düğmesini bir bağlantı bağlantısıyla değiştiriyorum. Form.submit () 'i çağırmak onsubmit'leri etkinleştirmediğinden, onu buluyorum ve kendim değerlendiriyorum (). Ama sadece orada olanı değerlendirmeden önce fonksiyonun var olup olmadığını kontrol etmek istiyorum. - 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>

DÜZENLEME: testOnsubmitAndSubmit işlevinde f parametresi eksik

Yukarıdakiler, onsubmitHTML niteliğini atasanız da JavaScript'te atamanıza bakılmaksızın çalışmalıdır :

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

1
f.onsubmit nereden geliyor?
Sanat

fbir form örneğidir. Bunu testOnsubmitAndSubmit işlevine bağımsız değişken olarak iletirsiniz. (Bu soru oldukça eski olduğunu biliyorum ama belki cevabım birisi biraz zaman :) kazandıracak)
zeroos

63

Deneyin

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

7
bu sadece bir örnek. Bunu button.onsubmit of Function olarak değiştirebilirsiniz
artemb

13

typeofOperatörü kısaca üçlü operatörle birlikte kullanabilirsiniz :

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

Eğer bir fonksiyonsa onu çağırırız ve dönüş değerini döndürürüz, aksi takdirde sadece döner true

Düzenle:

Gerçekten ne yapmak istediğinizden tam olarak emin değilim, ama neler olabileceğini açıklamaya çalışacağım.

onsubmitKodunuzu html'nizde ilan ettiğinizde , bir işleve dönüşür ve böylece JavaScript "dünya" dan çağrılabilir. Bu, bu iki yöntemin eşdeğer olduğu anlamına gelir:

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

Bu ikisi hem işlevler hem de çağrılabilir olacaktır. typeofOperatörü kullananlardan herhangi birini test edebilirsiniz "function".

Şimdi JavaScript aracılığıyla "onsubmit" özelliğine bir dize atarsanız, bu bir dize olarak kalır, dolayısıyla çağrılamaz. typeofOperatörü buna karşı uygularsanız, "string"bunun yerine alacağınıza dikkat edin "function".

Umarım bu birkaç şeyi açıklığa kavuşturur. Daha sonra, bu tür bir özelliğin (veya konu için herhangi bir tanımlayıcının) bir işlev ve çağrılabilir olup olmadığını bilmek istiyorsanız, typeofoperatör hile yapmalıdır. Yine de birden çok karede düzgün çalışıp çalışmadığından emin değilim.

Şerefe


Bunu onsubmit dışında test etmem gerekiyor.
Glen Solsberry

5

Hangi tarayıcıyı kullanıyorsunuz?

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

Bu bana functionIE7 ve FireFox'ta " " veriyor .


Onsubmit'iniz "iade geçerli ();" olsa bile?
Glen Solsberry

1
Evet - unutmayın, bir işlevin dışında "geri dönüş" yapamazsınız.
Greg

form.onsubmit, HTML özelliği olarak tanımlandığı sürece her zaman bir işlev olacaktır. Cevabımı gör.
Ionuț G. Stan

4

dizge tabanlı bir değişkeni örnek olarak kullanmak ve kullanmak instanceof Function İşlevi kaydettirirsiniz ... Değişkeni atarsınız ... değişkeni işlevin adı olarak kontrol edin ... ön işlem yapın ... işlevi yeni var'a atayın ... sonra işlevi çağırın.

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
Bu fn değişkenine gerçekten ihtiyacınız yok, sadece window [value] () kullanabilirsiniz;
Lajos Meszaros

1
evet biliyorum ama aynı zamanda uzun bir formatta anlamanın genellikle daha kolay olduğunu ve bu öncelikle girdinizin her durumda değerli olduğunu öğrenmek için bir site olduğunun farkındayım @LajosMeszaros
CrandellWS

3

Bir dizge değişmezi değil, gerçek işlevde typeof çağırdığınızdan emin olun:

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

typeof "x"; // returns "string"

typeof x; // returns "function"

3

Bu tekniği ihtiyaçlarınıza uyacak şekilde değiştirmeyi deneyebilirsiniz :

 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, form öğesinin HTML özniteliği olarak tanımlandığında her zaman bir işlev olacaktır. Bu, bir HTML öğesine eklenmiş bir tür anonim işlevdir, bu işaretçinin bu FORM öğesine bağlı olduğu ve ayrıca eventgönder olayıyla ilgili verileri içerecek bir parametre adı vardır.

Bu şartlar altında, bir tür işlemin sonucu olarak bir dizgeyi nasıl elde ettiğinizi anlamıyorum. Daha fazla ayrıntı vermelisiniz, daha iyi bir kod.

Düzenleme (ikinci düzenlemenize yanıt olarak):

HTML özniteliğine eklenen işleyicinin yukarıdaki koddan bağımsız olarak çalışacağına inanıyorum. Dahası, bunu bir şekilde durdurmayı deneyebilirsiniz, ancak FF 3, IE 8, Chrome 2 ve Opera 9'un ilk etapta HTML öznitelik işleyicisini çalıştırdığı ve daha sonra eklendiği görülüyor (jQuery ile test etmedim) ancak, ancak addEventListener ve attachEvent ile). Peki ... tam olarak ne başarmaya çalışıyorsun?

Bu arada, kodunuz çalışmıyor çünkü normal ifadeniz kesinlikle bir işlev olmayan "valid ();" dizesini çıkaracaktır.


2

Bir dizeyse, her zaman formda olduğunu varsayabilir / umabilirsiniz

return SomeFunction(arguments);

işlev adı için ayrıştırın ve ardından bu işlevin kullanılarak tanımlanıp tanımlanmadığına bakın

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

ben de bu çözünürlüğü eklemek üzereydim ... sadece işlevi belge / pencere düzeyinde kaydetmeyi unutmayın
CrandellWS

1

Eh, "return valid();" bir en düzeltmek böylece, bir dize.

Bunun yerine eklenmiş bir işlevi olup olmadığını kontrol etmek istiyorsanız, şunu deneyebilirsiniz:

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

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

1

Bence kafa karışıklığının kaynağı, bir düğümün özniteliği ile karşılık gelen özellik arasındaki ayrımdır .

Kullanıyorsunuz:

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

Doğrudan onsubmit özniteliğin değerini okuyorsunuz ( bir dize olmalıdır ). Bunun yerine, düğümün onsubmit özelliğine erişmelisiniz:

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

İşte hızlı bir test:

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

Bu, şunları verir:

form1 onsubmit özelliği: (işlev) işlev onsubmit (olay) {dönüş geçerli (); }
form1 onsubmit özniteliği: (dize) dönüş geçerli ()

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

1

Değil mi typeof xxx === 'function'en hızlı en iyi ve?

İnstanceof ve _underscore ile karşılaştırıldığında deneyebileceğiniz bir tezgah yaptım

  1. Sadece instanceof'tan daha hızlı gibi görünüyor (chrome kullanıyor)
  2. Değişken tanımlanmamışsa bir hataya neden olmaz

İşte bir tezgah: https://jsbench.me/qnkf076cqb/1


0

Chris West'inki gibi JavaScript bloglarında her zaman typeOf işlevlerinden birini kullanabilirsiniz . typeOf()İşlev için aşağıdaki gibi bir tanım kullanmak işe yarayacaktır:

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

Bu işlev (global ad alanında bildirilmiştir, şu şekilde kullanılabilir:

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

Bir işlev ise, "İşlev" döndürülür. Bir dizeyse, "Dize" döndürülür. Diğer olası değerler burada gösterilmektedir .


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

Bunun gibi basit bir kontrol, var olup olmadığını / tanımlanıp tanımlanmadığını size bildirir:

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

6
Bu işe yaramayacak. İf, onsubmit boş olmayan bir dizge olduğunda da TRUE olduğunu ileri sürer.
Seb

1
Bir şeyin bir işlev olup olmadığını test etmenin korkunç bir yolu - belirtildiği gibi ve daha açık olmak gerekirse: "doğru" olan herhangi bir şey, bu kodun "bir şeyler yapmasına" neden olur ve beklenen bu olmayabilir. This.onsubmit değeri 5 veya "merhaba" değerine ya da JavaScript'te true olarak değerlendirilen herhangi bir şeye ayarlanmışsa, beklenmedik davranışlar elde edersiniz.
Jason Bunting

Sorunun konusu, bir şeyin var olup olmadığının nasıl kontrol edileceğini sorar. Tüm önerdiğim buydu - ne fazla ne eksik.
Kon

Gerçekte değil - yayınlanan orijinal, "bir formun gönderildiğinde değerinin bir işlev olup olmadığını test etmesi gerektiğini" belirtir. Durumunuz this.onsubmit'in bir işlev olup olmadığı değildir, testiniz basitçe bunun "doğru" olup olmadığını sorar
Jason Bunting
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.