Як я можу викликати динамічно названий метод у Javascript?


113

Я динамічно працюю над створенням JavaScript, який буде вставлений у веб-сторінку під час її створення.

JavaScript буде використовуватися для заповнення на listboxоснові вибору в іншому listbox. Коли вибір одного listboxзмінено, він викличе ім'я методу на основі вибраного значення listbox.

Наприклад:

Listbox1 містить:

  • Colours
  • Shapes

Якщо Coloursвибрано, то він викличе populate_Coloursметод, який заповнює інший listbox.

Щоб уточнити моє запитання: як зробити цей populate_Coloursдзвінок у JavaScript?


Я б рекомендував проти цього на користь того, щоб місцеві відділення були єдиним методом "заселення". Це зробило б його більш випробуваним і виглядатиме менш "хакітним"
Аарон Пауелл

дивіться мою відповідь тут. дзвоніть по імені у 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
Дякуємо за відповідь. Біт вікна насправді кинув мене, поки я не погукнув його і не виявив, що глобальні об'єкти є частиною об'єкта вікна. Тепер це має сенс! Дякую. 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код :)
Стан Smulders

1
@peter Оскільки квадратні дужки не є доступними властивостями в цьому контексті, а позначають масив. Масиви не є функціями, тому ви не можете їх викликати.
user4642212

39

Як зазначає Триптих, ви можете викликати будь-яку глобальну функцію області, знайшовши її у вмісті хост-об'єкта.

Більш чистий метод, який забруднює глобальний простір імен набагато менше, полягає в тому, щоб явно помістити функції в масив безпосередньо так:

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)?
Кріс Б

Відповідаючи на власне запитання - я щойно перевірив вікно [dyn_functions ['populate_Colours'] (arg1, arg2)]; і це справді працює.
Кріс Б

4
Як вказує epascarello, вам зазвичай не потрібно "window" - "dyn_functions ['populate_Colours'] (arg1, arg2);" буду працювати. Насправді, не включаючи ім'я глобального об'єкта, зробить код більш портативним, якщо ви пишете підпрограми, які коли-небудь можуть використовуватися в середовищі JS, крім веб-браузера. Однак це є виключенням: якщо у вас є функція локальної змінної під назвою dyn_functions у функції, вам потрібно буде бути більш конкретним, про яке ви посилаєтесь, але цю ситуацію найкраще уникати (все-таки мати розумні умови іменування) у будь-якому випадку.
Девід Спіллетт

1
Оскільки ця публікація починає з '09 року, ви, мабуть, знаєте це вже зараз, але ви створюєте масив, а потім присвоюєте властивості масиву (а не індекси). Ви можете також зробити це, var dyn_functions = {};щоб вам не потрібно створювати масив ... Хоча це не величезна проблема.
Девід Шеррет

надто складна відповідь, але все-таки працює. Я думаю, що завантаження ресурсів для сценарію, коли у мене є ряд візерункових функцій, і мені потрібне дерево рішення для вибору виконання, цей метод може бути надмірно складним для виконання завдання. Хоча, якби я з'єднував об'єкт власного класу, це був би кращий підхід до визначення самого об'єкта.
GoldBishop

30

Я рекомендував би НЕ використовувати global/ window/ evalдля цієї мети.
Натомість зробіть це так:

визначити всі методи як властивості Handler:

var Handler={};

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

Тепер назвіть це так

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

Вихід: Джеррі


17

ви можете зробити так:

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

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

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

він буде обробляти самі параметри.


uncaught посилання помилки - functionName не визначено
brianlmerritt

@brianlmerritt, ви повинні визначити значення для functionName... відповідач зробив припущення, що ви вже це визначили.
GoldBishop

Здається, нову функцію () не можна використовувати для цієї мети.
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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.