Javascript'te dinamik olarak adlandırılmış bir yöntemi nasıl çağırırım?


113

Oluşturulduğu sırada bir web sayfasına eklenecek bazı JavaScript'leri dinamik olarak oluşturmak için çalışıyorum.

JavaScript, bir listboxdiğerindeki seçime göre bir doldurmak için kullanılacaktır listbox. Birinin seçimi listboxdeğiştirildiğinde, seçilen değerine göre bir yöntem adı çağıracaktır listbox.

Örneğin:

Listbox1 içerir:

  • Colours
  • Shapes

Seçilirse Colours, populate_Coloursdiğerini dolduran bir yöntemi çağıracaktır listbox.

Sorumu açıklığa kavuşturmak için: Bu populate_Coloursaramayı JavaScript'te nasıl yaparım ?


Buna karşı, yerel şubelerin tek bir 'doldurma' yöntemiyle olmasını öneririm. Daha test edilebilir hale getirir ve daha az "hacky" görünmesini sağlar
Aaron Powell

cevabımı burada görün. javascript'te isme göre çağrı
Hugo R

Yanıtlar:


208

populate_ColoursYöntemin genel ad alanında olduğunu varsayarsak, hem tüm nesne özelliklerine, nesnenin ilişkilendirilebilir bir diziymiş gibi erişilebileceğinden hem de tüm genel nesnelerin aslında windowana nesnenin özellikleri olduğundan yararlanan aşağıdaki kodu kullanabilirsiniz .

var method_name = "Colours";
var method_prefix = "populate_";

// Call function:
window[method_prefix + method_name](arg1, arg2);

9
Cevabınız için teşekkürler. 'Pencere' biti, Google'da aranana ve global nesnelerin pencere nesnesinin parçası olduğunu bulana kadar beni gerçekten savurdu. Şimdi bir anlam kazandı! Teşekkür ederim. Bilginize Burada bununla
Chris B

3
Hedeflediğim işlevlerin jQuery "fn" ad alanında olması dışında benzer bir şey yaptım. Örneğin,$.fn[method_prefix + method_name](arg1, arg2);
codecraig

1
Güzel. Bir try/ catchblok eklemeye değer , belki.
LeeGee

Bu bazıları için açık olabilir, ancak çalışmasını sağlayamayanlar için: işlevi kendinizin dışına atın $(function () {ve window.loadkodlayın :)
Stan Smulders

1
@peter Çünkü köşeli parantezler bu bağlamda özellik erişimcileri değildir, ancak bir Diziyi belirtir. Diziler işlev değildir, bu yüzden onları çağıramazsınız.
user4642212

39

Triptych'in işaret ettiği gibi, herhangi bir genel kapsam işlevini ana bilgisayar nesnesinin içeriğinde bularak çağırabilirsiniz.

Küresel ad alanını çok daha az kirleten daha temiz bir yöntem, işlevleri doğrudan şu şekilde bir diziye açıkça koymaktır:

var dyn_functions = [];
dyn_functions['populate_Colours'] = function (arg1, arg2) { 
                // function body
           };
dyn_functions['populate_Shapes'] = function (arg1, arg2) { 
                // function body
           };
// calling one of the functions
var result = dyn_functions['populate_Shapes'](1, 2);
// this works as well due to the similarity between arrays and objects
var result2 = dyn_functions.populate_Shapes(1, 2);

Bu dizi aynı zamanda genel ana makine nesnesi dışındaki bir nesnenin özelliği de olabilir, bu da jQuery gibi birçok JS kitaplığının yaptığı gibi kendi ad alanınızı etkili bir şekilde oluşturabileceğiniz anlamına gelir. Bu, aynı sayfaya birden fazla ayrı yardımcı program kitaplığı eklerseniz / dahil ettiğinizde çakışmaları azaltmak için yararlıdır ve (tasarımınızın diğer bölümleri izin verirse) kodu diğer sayfalarda yeniden kullanmayı kolaylaştırabilir.

Bunun gibi daha temiz bulabileceğiniz bir nesne de kullanabilirsiniz:

var dyn_functions = {};
dyn_functions.populate_Colours = function (arg1, arg2) { 
                // function body
           };
dyn_functions['populate_Shapes'] = function (arg1, arg2) { 
                // function body
           };
// calling one of the functions
var result = dyn_functions.populate_Shapes(1, 2);
// this works as well due to the similarity between arrays and objects
var result2 = dyn_functions['populate_Shapes'](1, 2);

Bir dizi veya bir nesneyle, işlevleri ayarlama veya bunlara erişme yöntemlerinden birini kullanabileceğinizi ve tabii ki diğer nesneleri de orada depolayabileceğinizi unutmayın. O kadar dinamik olmayan içerik için her iki yöntemin sözdizimini, JS değişmez gösterimini kullanarak daha da azaltabilirsiniz:

var dyn_functions = {
           populate_Colours:function (arg1, arg2) { 
                // function body
           };
         , populate_Shapes:function (arg1, arg2) { 
                // function body
           };
};

Düzenleme: Elbette daha büyük işlevsellik blokları için, yukarıdakileri, kod özelliklerini düzenli bir şekilde kapsüllemenin popüler bir yolu olan çok yaygın "modül modeline" genişletebilirsiniz.


Temiz tutmanın güzel bir yolu. Yine de yöntemi nasıl çağırırım? Pencere [dyn_functions ['populate_Colours'] (arg1, arg2) çalışır mı?
Chris B

Kendi sorumu cevaplıyorum - Az önce [dyn_functions ['populate_Colours'] (arg1, arg2)] penceresini test ettim; ve gerçekten işe yarıyor.
Chris B

4
Epascarello'nun işaret ettiği gibi, genellikle "window" - "dyn_functions ['populate_Colours'] (arg1, arg2);" çalışacak. Aslında, global nesnenin adını eklememek, bir web tarayıcısı dışında bir JS ortamında kullanılabilecek rutinler yazıyorsanız, kodu daha taşınabilir hale getirecektir. Yine de bunun bir istisnası vardır: eğer bir işlevde dyn_functions adında yerel bir değişkeniniz varsa, o zaman bahsettiğiniz daha spesifik olmanız gerekir, ancak bu durumdan kaçınılması en iyisidir (mantıklı adlandırma kurallarına sahip olarak).
David Spillett

1
Bu gönderi '09'dan geldiğinden, muhtemelen bunu şimdiye kadar biliyorsunuzdur, ancak bir dizi oluşturuyorsunuz, ardından dizinin özelliklerine atıyorsunuz (dizinlere değil). Siz de yapabilir var dyn_functions = {};Eğer gereksiz bir dizi oluşturmak kalmamak bu olsa büyük bir sorun değildir ....
David Sherret

aşırı karmaşık cevap ama işe yarıyor. Bir dizi desenli fonksiyona sahip olduğum ve yürütmeyi seçmek için bir karar ağacına ihtiyaç duyduğum senaryo için kaynak yükünü düşünürdüm, bu yöntemin görevi gerçekleştirmek için aşırı karmaşık olabileceğini düşünüyorum. Yine de, kendi sınıf nesnemi bağlasaydım, nesnenin kendisini tanımlamak için tercih edilen yaklaşım bu olurdu.
GoldBishop

30

Ben öneriyoruz DEĞİL kullanmak global/ window/ evalbu amaçla.
Bunun yerine, şu şekilde yapın:

tüm yöntemleri İşleyicinin özellikleri olarak tanımlayın:

var Handler={};

Handler.application_run = function (name) {
console.log(name)
}

Şimdi böyle söyle

var somefunc = "application_run";
Handler[somefunc]('jerry');

Çıktı: jerry


17

bunu şu şekilde yapabilirsin:

function MyClass() {
    this.abc = function() {
        alert("abc");
    }
}

var myObject = new MyClass();
myObject["abc"]();

5

Bir ServiceWorkerveya içinde Worker, windowşununla değiştirin self:

self[method_prefix + method_name](arg1, arg2);

Çalışanların DOM'a erişimi yoktur, bu nedenle windowgeçersiz bir referanstır. Bu amaç için eşdeğer genel kapsam tanımlayıcısı self.


2

Diğer cevaplardan bazılarının önerdiği gibi pencereyi kullanmanızı tavsiye etmem. kullanımthis göre ve kapsamı alın.

this['yourDynamicFcnName'](arguments);

Başka bir düzgün numara, farklı kapsamlar içinde arama yapmak ve bunu kalıtım için kullanmaktır. Diyelim ki işlevi iç içe geçirdiniz ve global pencere nesnesine erişmek istiyorsunuz. Bunu yapabilirsin:

this['yourDynamicFcnName'].call(window, arguments);

1

Merhaba bunu dene,

 var callback_function = new Function(functionName);
 callback_function();

parametrelerin kendisini idare edecektir.


yakalanmamış referans hatası - functionName tanımlanmadı
brianlmerritt

@brianlmerritt için değeri tanımlamalısınız functionName... yanıtlayan kişi bunu zaten tanımlamış olduğunuzu varsaydı .
GoldBishop

Görünüşe göre new Function () bu amaçla bu şekilde kullanılamaz.
JCH77

-1

İşte bir fonksiyonun varlığını kontrol etmek ve dinamik olarak çalışan triyaj yapmak için çalışan ve basit bir çözüm başka bir fonksiyon tarafından ;

Tetikleme işlevi

function runDynmicFunction(functionname){ 

    if (typeof window[functionname] == "function"  ) { //check availability

        window[functionname]("this is from the function it "); //run function and pass a parameter to it
    }
}

ve şimdi işlevi dinamik olarak oluşturabilirsiniz, belki bunun gibi php kullanarak

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

artık dinamik olarak oluşturulmuş olayı kullanarak işlevi çağırabilirsiniz

<?php

$name_frm_somware ="runThis_func";

echo "<input type='button' value='Button' onclick='runDynmicFunction(\"".$name_frm_somware."\");'>";

?>

tam ihtiyacınız olan HTML kodu

<input type="button" value="Button" onclick="runDynmicFunction('runThis_func');">

-3

Şununla dene:

var fn_name = "Colours",
fn = eval("populate_"+fn_name);
fn(args1,argsN);

Bu kalıbı kullanmanın etkileri nelerdir? evalİşlevin kullanımıyla ilgili bazı tuhaf yan etkileri olduğunu okudum . Son çare olmadıkça genellikle ondan uzak durmaya çalışırım.
GoldBishop
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.