Làm cách nào để gọi một phương thức có tên động trong Javascript?


113

Tôi đang làm việc để tạo động một số JavaScript sẽ được chèn vào một trang web khi nó đang được xây dựng.

JavaScript sẽ được sử dụng để điền một listboxdựa trên lựa chọn trong một lựa chọn khác listbox. Khi lựa chọn một trong những listboxthay đổi, nó sẽ gọi một tên phương thức dựa trên giá trị đã chọn của listbox.

Ví dụ:

Listbox1 chứa đựng:

  • Colours
  • Shapes

Nếu Coloursđược chọn thì nó sẽ gọi một populate_Coloursphương thức điền vào một phương thức khác listbox.

Để làm rõ câu hỏi của tôi: Làm cách nào để thực hiện populate_Colourscuộc gọi đó trong JavaScript?


Tôi khuyên bạn không nên làm điều này để ủng hộ việc có các chi nhánh địa phương trong một phương pháp 'cư trú' duy nhất. Nó sẽ làm cho nó kiểm chứng hơn và tìm kiếm ít "hacky"
Aaron Powell

xem câu trả lời của tôi ở đây. gọi bằng tên trong javascript
Hugo R

Câu trả lời:


208

Giả sử populate_Coloursphương thức nằm trong không gian tên chung, bạn có thể sử dụng mã sau, mã này khai thác cả hai thuộc tính đối tượng có thể được truy cập như thể đối tượng là một mảng kết hợp và tất cả các đối tượng toàn cục thực sự là thuộc tính của windowđối tượng chủ.

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

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

9
Cảm ơn vì sự trả lời. Bit 'cửa sổ' thực sự đã làm tôi say mê cho đến khi tôi tìm kiếm nó và thấy rằng các đối tượng toàn cục là một phần của đối tượng cửa sổ. Bây giờ nó có ý nghĩa! Cảm ơn bạn. FYI Tôi tìm thấy một trang tốt về nó ở đây devlicio.us/blogs/sergio_pereira/archive/2009/02/09/...
Chris B

3
Tôi đã làm điều gì đó tương tự ngoại trừ các chức năng tôi đang nhắm mục tiêu nằm trong không gian tên jQuery "fn". Ví dụ:$.fn[method_prefix + method_name](arg1, arg2);
codecraig

1
Đẹp. Worth thêm một try/ catchkhối, có lẽ.
LeeGee

Đây có thể là hiển nhiên đối với một số người, nhưng đối với những người không thể có được nó để làm việc: ném các chức năng bên ngoài của bạn $(function () {window.loadcode :)
Stan Smulders

1
@peter Vì dấu ngoặc vuông không phải là trình truy cập thuộc tính trong ngữ cảnh này, nhưng biểu thị một Mảng. Mảng không phải là hàm, vì vậy bạn không thể gọi chúng.
user4642212

39

Như Triptych đã chỉ ra, bạn có thể gọi bất kỳ hàm phạm vi toàn cầu nào bằng cách tìm hàm đó trong nội dung của đối tượng máy chủ.

Một phương pháp sạch hơn, ít gây ô nhiễm không gian tên chung hơn nhiều, là đặt các hàm vào một mảng một cách rõ ràng trực tiếp như sau:

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

Mảng này cũng có thể là một thuộc tính của một số đối tượng khác với đối tượng máy chủ lưu trữ toàn cầu, nghĩa là bạn có thể tạo không gian tên của riêng mình một cách hiệu quả như nhiều thư viện JS chẳng hạn như jQuery. Điều này hữu ích để giảm xung đột nếu / khi bạn bao gồm nhiều thư viện tiện ích riêng biệt trong cùng một trang và (các phần khác của thiết kế của bạn cho phép) có thể giúp sử dụng lại mã trong các trang khác dễ dàng hơn.

Bạn cũng có thể sử dụng một đối tượng như vậy, mà bạn có thể thấy rõ ràng hơn:

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

Lưu ý rằng với một mảng hoặc một đối tượng, bạn có thể sử dụng một trong hai phương pháp thiết lập hoặc truy cập các hàm và tất nhiên có thể lưu trữ các đối tượng khác trong đó. Bạn có thể giảm thêm cú pháp của một trong hai phương thức cho nội dung không động bằng cách sử dụng ký hiệu chữ JS như sau:

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

Chỉnh sửa: tất nhiên đối với các khối chức năng lớn hơn, bạn có thể mở rộng ở trên thành "mẫu mô-đun" rất phổ biến, đây là một cách phổ biến để đóng gói các tính năng mã một cách có tổ chức.


Đó là một cách tốt để giữ cho nó sạch sẽ. Tôi sẽ gọi phương thức như thế nào? Window [dyn_functions ['populate_Colours'] (arg1, arg2) có hoạt động không?
Chris B

Trả lời câu hỏi của riêng tôi - Tôi vừa thử nghiệm window [dyn_functions ['populate_Colours'] (arg1, arg2)]; và nó thực sự hoạt động.
Chris B

4
Như epascarello đã chỉ ra, bạn thường không cần "window" - "dyn_functions ['populate_Colours'] (arg1, arg2);" sẽ làm việc. Trên thực tế, việc không bao gồm tên của đối tượng toàn cục sẽ làm cho mã dễ di động hơn nếu bạn đang viết các quy trình có thể được sử dụng trong môi trường JS không phải là trình duyệt web. Tuy nhiên, có một ngoại lệ cho điều này: nếu bạn có một biến cục bộ được gọi là dyn_functions trong một hàm thì bạn sẽ cần phải cụ thể hơn mà bạn đang đề cập đến, nhưng tốt nhất bạn nên tránh trường hợp này (bằng cách có các quy ước đặt tên hợp lý).
David Spillett

1
Vì bài đăng này là từ '09 đến bây giờ bạn có thể biết điều này, nhưng bạn đang tạo một mảng, sau đó gán cho các thuộc tính của mảng (không phải chỉ mục). Bạn cũng có thể làm var dyn_functions = {};vì vậy bạn không cần tạo một mảng ... đây không phải là một vấn đề lớn.
David Sherret

câu trả lời quá phức tạp nhưng không hoạt động. Tôi sẽ nghĩ rằng tải tài nguyên cho kịch bản mà tôi có một loạt các hàm theo mẫu và tôi cần một cây quyết định để chọn việc thực thi, phương pháp này có thể quá phức tạp để thực hiện tác vụ. Mặc dù, nếu tôi đang kết nối đối tượng lớp của riêng mình, đây sẽ là cách tiếp cận ưu tiên để xác định chính đối tượng.
GoldBishop

30

Tôi khuyên bạn KHÔNG nên sử dụng global/ window/ evalcho mục đích này.
Thay vào đó, hãy làm theo cách này:

định nghĩa tất cả các phương thức là thuộc tính của Handler:

var Handler={};

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

Bây giờ hãy gọi nó như thế này

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

Đầu ra: jerry


17

bạn có thể làm như thế này:

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

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

5

Trong một ServiceWorkerhoặc Worker, thay thế windowbằng self:

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

Người lao động không có quyền truy cập vào DOM, do đó windowlà một tham chiếu không hợp lệ. Định danh phạm vi toàn cầu tương đương cho mục đích này là self.


2

Tôi không khuyên bạn nên sử dụng cửa sổ như một số câu trả lời khác đề xuất. Sử dụng thisvà phạm vi phù hợp.

this['yourDynamicFcnName'](arguments);

Một mẹo nhỏ khác là gọi trong các phạm vi khác nhau và sử dụng nó để kế thừa. Giả sử bạn đã lồng hàm và muốn truy cập vào đối tượng cửa sổ chung. Bạn có thể làm điều này:

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

1

Xin chào, hãy thử cái này,

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

nó sẽ tự xử lý các tham số.


lỗi tài liệu tham khảo còn tự do - functionName không được định nghĩa
brianlmerritt

@brianlmerritt bạn phải xác định giá trị cho functionName... người trả lời đưa ra giả định rằng bạn đã xác định giá trị đó.
GoldBishop

Có vẻ như Hàm mới () không thể được sử dụng như vậy cho mục đích này.
JCH77

-1

Đây là một giải pháp hoạt động và đơn giản để kiểm tra sự tồn tại của một hàmphân loại động hàm đó bằng một hàm khác;

Chức năng kích hoạt

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

và bây giờ bạn có thể tạo hàm động có thể bằng cách sử dụng php như thế này

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

bây giờ bạn có thể gọi hàm bằng sự kiện được tạo động

<?php

$name_frm_somware ="runThis_func";

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

?>

mã HTML chính xác bạn cần là

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

-3

Hãy thử với cái này:

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

Ý nghĩa của việc sử dụng mẫu này là gì? Tôi đã đọc rằng evalchức năng này có một số tác dụng phụ wierd liên quan đến việc sử dụng nó. Tôi thường cố gắng tránh xa nó, trừ khi đó là biện pháp cuối cùng.
GoldBishop
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.