ฉันจะเรียกเมธอดที่มีชื่อแบบไดนามิกใน Javascript ได้อย่างไร


114

ฉันกำลังดำเนินการสร้าง JavaScript แบบไดนามิกซึ่งจะแทรกลงในหน้าเว็บขณะที่กำลังสร้าง

จาวาสคริปต์จะใช้ในการเติมขึ้นอยู่กับตัวเลือกในอีกlistbox listboxเมื่อการเลือกlistboxมีการเปลี่ยนแปลงจะเรียกชื่อเมธอดตามค่าที่เลือกของlistbox.

ตัวอย่างเช่น:

Listbox1 ประกอบด้วย:

  • Colours
  • Shapes

หากColoursถูกเลือกแล้วมันจะเรียกpopulate_Coloursวิธีการที่ populates listboxอื่น

เพื่อชี้แจงคำถามของฉัน: ฉันจะpopulate_Coloursโทรใน JavaScript ได้อย่างไร


ฉันไม่แนะนำให้ทำเช่นนี้เพื่อให้มีสาขาในท้องถิ่นในวิธี 'เติมข้อมูล' เพียงวิธีเดียว มันจะทำให้ทดสอบได้มากขึ้นและดู "แฮ็ก" น้อยลง
Aaron Powell

ดูคำตอบของฉันที่นี่ เรียกชื่อใน javascript
Hugo R

คำตอบ:


208

สมมติว่าpopulate_Coloursเมธอดอยู่ในเนมสเปซส่วนกลางคุณอาจใช้โค้ดต่อไปนี้ซึ่งใช้ประโยชน์จากทั้งสองอย่างที่คุณสมบัติอ็อบเจ็กต์ทั้งหมดอาจเข้าถึงได้ราวกับว่าอ็อบเจ็กต์เป็นอาร์เรย์ที่เชื่อมโยงกันและอ็อบเจ็กต์ส่วนกลางทั้งหมดเป็นคุณสมบัติของwindowอ็อบเจ็กต์โฮสต์

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

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

9
ขอบคุณสำหรับการตอบกลับ 'หน้าต่าง' ทำให้ฉันรู้สึกแย่จริงๆจนกระทั่งฉัน googled และพบว่า global objects เป็นส่วนหนึ่งของ window object ตอนนี้เข้าท่าแล้ว! ขอบคุณ. FYI ฉันพบเพจดีๆเกี่ยวกับมันที่นี่ devlicio.us/blogs/sergio_pereira/archive/2009/02/09/…
Chris B

3
ฉันทำบางอย่างที่คล้ายกันยกเว้นฟังก์ชันที่ฉันกำหนดเป้าหมายอยู่ในเนมสเปซ jQuery "fn" ตัวอย่างเช่น$.fn[method_prefix + method_name](arg1, arg2);
codecraig

1
ดี. อาจจะคุ้มค่ากับการเพิ่มtry/ catchบล็อก
LeeGee

สิ่งนี้อาจชัดเจนสำหรับบางคน แต่สำหรับผู้ที่ไม่สามารถใช้งานได้ให้โยนฟังก์ชั่นภายนอก$(function () {และwindow.loadรหัสของคุณ:)
Stan Smulders

1
@peter เนื่องจากวงเล็บเหลี่ยมไม่ใช่ตัวเข้าถึงคุณสมบัติในบริบทนี้ แต่แสดงถึง Array อาร์เรย์ไม่ใช่ฟังก์ชันดังนั้นคุณจึงไม่สามารถเรียกใช้งานได้
user4642212

39

ตามที่ Triptych ชี้ให้เห็นคุณสามารถเรียกใช้ฟังก์ชันขอบเขตส่วนกลางใด ๆ โดยค้นหาในเนื้อหาของวัตถุโฮสต์

วิธีการที่สะอาดกว่าซึ่งก่อให้เกิดมลพิษต่อเนมสเปซทั่วโลกน้อยกว่ามากคือการใส่ฟังก์ชันลงในอาร์เรย์โดยตรงดังนี้:

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

อาร์เรย์นี้อาจเป็นคุณสมบัติของออบเจ็กต์บางอย่างนอกเหนือจากอ็อบเจ็กต์โฮสต์ส่วนกลางเช่นกันซึ่งหมายความว่าคุณสามารถสร้างเนมสเปซของคุณเองได้อย่างมีประสิทธิภาพเหมือนกับไลบรารี JS จำนวนมากเช่น jQuery สิ่งนี้มีประโยชน์ในการลดความขัดแย้งหาก / เมื่อคุณรวมไลบรารียูทิลิตี้แยกกันหลายไลบรารีไว้ในหน้าเดียวกันและ (ส่วนอื่น ๆ ของการอนุญาตการออกแบบของคุณ) ช่วยให้สามารถใช้โค้ดซ้ำในหน้าอื่น ๆ ได้ง่ายขึ้น

คุณยังสามารถใช้วัตถุเช่นนี้ซึ่งคุณอาจพบว่าสะอาดกว่า:

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

โปรดทราบว่าด้วยอาร์เรย์หรือออบเจ็กต์คุณสามารถใช้วิธีการตั้งค่าหรือเข้าถึงฟังก์ชั่นใดก็ได้และแน่นอนว่าสามารถจัดเก็บอ็อบเจ็กต์อื่น ๆ ไว้ในนั้นด้วย คุณสามารถลดไวยากรณ์ของวิธีใดวิธีหนึ่งสำหรับเนื้อหาที่ไม่ใช่ไดนามิกนั้นได้โดยใช้สัญกรณ์ตัวอักษร JS ดังนี้:

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

แก้ไข: แน่นอนว่าสำหรับบล็อกการทำงานที่ใหญ่ขึ้นคุณสามารถขยายข้างต้นเป็น "รูปแบบโมดูล" ทั่วไปซึ่งเป็นวิธีที่นิยมในการห่อหุ้มคุณลักษณะของโค้ดในลักษณะที่เป็นระเบียบ


นั่นเป็นวิธีที่ดีในการรักษาความสะอาด ฉันจะเรียกวิธีการอย่างไร หน้าต่าง [dyn_functions ['populate_Colours'] (arg1, arg2) จะทำงานหรือไม่
Chris B

ตอบคำถามของตัวเอง - ฉันเพิ่งทดสอบ window [dyn_functions ['populate_Colours'] (arg1, arg2)]; และมันได้ผลจริง
Chris B

4
ตามที่ epascarello ชี้ให้เห็นโดยทั่วไปคุณไม่จำเป็นต้องมี "window" - "dyn_functions ['populate_Colours'] (arg1, arg2);" จะทำงาน. ในความเป็นจริงการไม่รวมชื่อวัตถุส่วนกลางจะทำให้โค้ดพกพาสะดวกยิ่งขึ้นหากคุณเขียนกิจวัตรที่อาจเคยใช้ในสภาพแวดล้อม JS อื่นที่ไม่ใช่เว็บเบราว์เซอร์ มีข้อยกเว้นสำหรับสิ่งนี้: หากคุณมีตัวแปรท้องถิ่นที่เรียกว่า dyn_functions ในฟังก์ชันคุณจะต้องเจาะจงมากขึ้นที่คุณกำลังอ้างถึง แต่สถานการณ์นี้ควรหลีกเลี่ยงได้ดีที่สุด (โดยมีหลักการตั้งชื่อที่เหมาะสม) อย่างไรก็ตาม
David Spillett

1
เนื่องจากโพสต์นี้มาจาก '09 คุณอาจจะรู้แล้วในตอนนี้ แต่คุณกำลังสร้างอาร์เรย์จากนั้นกำหนดให้กับคุณสมบัติของอาร์เรย์ (ไม่ใช่ดัชนี) คุณอาจทำได้var dyn_functions = {};เช่นกันโดยไม่จำเป็นต้องสร้างอาร์เรย์โดยไม่จำเป็น ... นี่ไม่ใช่ปัญหาใหญ่
David Sherret

คำตอบที่ซับซ้อนเกินไป แต่ได้ผล ฉันคิดว่าทรัพยากรโหลดสำหรับสถานการณ์ที่ฉันมีชุดของฟังก์ชันที่มีลวดลายและฉันต้องการโครงสร้างการตัดสินใจเพื่อเลือกการดำเนินการวิธีนี้อาจซับซ้อนเกินไปในการทำงาน แม้ว่าฉันจะเดินสายอ็อบเจ็กต์คลาสของตัวเองนี่จะเป็นแนวทางที่ดีที่สุดในการกำหนดอ็อบเจกต์เอง
GoldBishop

31

ฉันไม่แนะนำให้ใช้global/ window/ evalเพื่อจุดประสงค์นี้
ให้ทำวิธีนี้แทน:

กำหนดวิธีการทั้งหมดเป็นคุณสมบัติของ Handler:

var Handler={};

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

เดี๋ยวนี้เรียกแบบนี้

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

เอาท์พุต:เจอร์รี่


กรณีเมื่อนำเข้าฟังก์ชันจากไฟล์อื่น

import { func1, func2 } from "../utility";

const Handler= {
  func1,
  func2
};

Handler["func1"]("sic mundus");
Handler["func2"]("creatus est");


5

ภายในServiceWorkerหรือWorkerแทนที่windowด้วยself:

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

คนงานไม่มีสิทธิ์เข้าถึง DOM ดังนั้นจึงwindowเป็นการอ้างอิงที่ไม่ถูกต้อง selfเทียบเท่าระบุขอบเขตทั่วโลกเพื่อวัตถุประสงค์นี้คือ


2

ฉันไม่แนะนำให้ใช้หน้าต่างตามที่คำตอบอื่น ๆ แนะนำ ใช้thisและขอบเขตตามนั้น

this['yourDynamicFcnName'](arguments);

เคล็ดลับอีกอย่างหนึ่งคือการโทรภายในขอบเขตที่แตกต่างกันและใช้เพื่อการสืบทอด สมมติว่าคุณได้ซ้อนฟังก์ชันและต้องการเข้าถึงวัตถุหน้าต่างส่วนกลาง คุณสามารถทำได้:

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

1

สวัสดีลองสิ่งนี้

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

มันจะจัดการกับพารามิเตอร์เอง


ข้อผิดพลาดในการอ้างอิงที่ไม่ถูกจับ
functionName

@brianlmerritt คุณต้องกำหนดค่าสำหรับfunctionName... ผู้ตอบตั้งสมมติฐานที่คุณได้กำหนดไว้แล้ว
GoldBishop

ดูเหมือนว่า Function () ใหม่จะไม่สามารถใช้เพื่อจุดประสงค์นี้ได้
JCH77

-1

นี่คือวิธีแก้ปัญหาที่ใช้งานง่ายและใช้งานง่ายสำหรับการตรวจสอบการมีอยู่ของฟังก์ชันและการตรวจสอบฟังก์ชันนั้นแบบไดนามิกโดยฟังก์ชันอื่น

ฟังก์ชันทริกเกอร์

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

และตอนนี้คุณสามารถสร้างฟังก์ชันแบบไดนามิกได้แล้วโดยใช้ php เช่นนี้

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

ตอนนี้คุณสามารถเรียกใช้ฟังก์ชันโดยใช้เหตุการณ์ที่สร้างขึ้นแบบไดนามิก

<?php

$name_frm_somware ="runThis_func";

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

?>

โค้ด HTML ที่คุณต้องการคือ

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

-3

ลองใช้สิ่งนี้:

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

ความหมายของการใช้รูปแบบนี้คืออะไร? ฉันได้อ่านว่าevalฟังก์ชั่นมีอะไรบางอย่างแปลกผลข้างเคียงที่เกี่ยวข้องกับการใช้งาน โดยทั่วไปฉันพยายามที่จะอยู่ห่างจากมันเว้นแต่จะเป็นทางเลือกสุดท้าย
GoldBishop
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.