2012-12-19 31 views
7

thể trùng lặp:
How to get function parameter names/values dynamically from javascriptRegular Expression để có được danh sách tham số từ định nghĩa hàm

Tôi hiện đang làm việc trên một dự án trong javascript (Node.js) có tôi cố gắng lấy một mảng tham số tên (KHÔNG giá trị, tôi không cần đối số) từ một hàm. Tôi hiện đang sử dụng Function.toString() để có được chuỗi chức năng và sau đó chạy một regex chống lại đó để có được danh sách tham số của tôi.

Hãy lấy ví dụ đơn giản sau:

var myFunction = function (paramOne, paramTwo) { ... } 

Chạy regex của tôi chống lại điều này, và sau đó làm một số chuỗi ma thuật (tách, vv) Tôi mong chờ một mảng trở lại như thế này:

paramList = ['paramOne', 'paramTwo'] 

Tôi có một cái gì đó hoạt động nhưng tôi cảm thấy như nó có thể không phải là giải pháp tốt nhất cho một số ký tự funky javascript cho phép bạn sử dụng cho tên biến và javascript sẽ cho phép bạn xác định các chức năng trên nhiều dòng.

Dưới đây là những gì tôi hiện có:

function.*[\w\s$]*(\((.*[\w\s,$]*)\)) 

này mang lại cho tôi tôi "trận đấu" trong nhóm 1 và sau đó danh sách param của tôi mà không Parens trong nhóm 2, đó là mát mẻ. Đây có thực sự là cách tốt nhất để làm những gì tôi muốn không? Có một biểu thức chính quy tốt hơn tôi có thể sử dụng cho điều này? Tôi không thực sự tìm kiếm một cái gì đó "đơn giản" nhưng thực sự chỉ là một cái gì đó mà có thể bắt tất cả các tình huống có thể xảy ra.

Bất kỳ trợ giúp nào sẽ được đánh giá cao và cảm ơn bạn rất nhiều!

Trả lời

16

Điều đơn giản nhất là chụp tất cả mọi thứ trong nhóm parens đầu tiên, sau đó sử dụng split(/\s*,\s*/) để lấy mảng.

Ví dụ:

var str = "function( one ,\ntwo,three , four ) { laksjdfl akjsdflkasjdfl }"; 
 
var args = /\(\s*([^)]+?)\s*\)/.exec(str); 
 
if (args[1]) { 
 
    args = args[1].split(/\s*,\s*/); 
 
} 
 
snippet.log("args: " + JSON.stringify(args));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Làm thế nào các công trình trên:

  1. Chúng tôi sử dụng /\(*([^)]+?) *\)/ để phù hợp với dấu ngoặc mở đầu tiên (\( từ ( là đặc biệt trong regexes), theo sau là bất kỳ khoảng trắng tùy chọn nào, tiếp theo là nhóm chụp c apturing tất cả mọi thứ nhưng một đóng ngoặc (nhưng không tham lam), theo sau là bất kỳ số lượng khoảng trắng tùy chọn, theo sau là đóng ).

  2. Nếu chúng tôi thành công, chúng tôi tách sử dụng /\s*,\s*/, có nghĩa là chúng tôi chia trên chuỗi đó là không hoặc nhiều ký tự khoảng trắng (\s*) tiếp theo là một dấu phẩy sau đó không hoặc nhiều ký tự khoảng trắng (điều khoảng trắng này là lý do tại sao args trong chức năng ví dụ của tôi rất lạ).

Như bạn có thể nhìn thấy từ ví dụ này, này xử lý khoảng trắng hàng đầu (sau khi ( và trước đối số đầu tiên), khoảng trắng xung quanh dấu phẩy, và dấu khoảng trắng   — bao gồm ngắt dòng. Nó không không cố gắng xử lý các nhận xét trong danh sách đối số, điều này sẽ làm phức tạp rõ ràng mọi thứ.


Lưu ý bên cạnh: Hãy chắc chắn kiểm tra trên các trình duyệt đích của bạn, Function#toString trả về một số dạng mã nguồn là một tính năng không chuẩn. Nó được hỗ trợ rộng rãi (trong các trình duyệt máy tính để bàn), nhưng không được hỗ trợ chuẩn. Lưu ý rằng một số trình duyệt sẽ bao gồm nhận xét, những người khác sẽ không có; nếu ai đó bao gồm các bình luận trong các đối số chức năng, nó cũng có thể làm hỏng phân tích cú pháp của bạn về chúng. Bạn có thể đá xung quanh Prototype source code for its Function#argumentNames extension, như họ đã từng xuống đường này ...

+0

Làm thế nào để bạn nghĩ rằng tôi nên đi về điều đó? Đó là những gì tôi đang cố gắng để làm với regex của tôi, nhưng có lẽ có một cách tiếp cận khác nhau? Bạn có nghĩ rằng tôi chỉ có thể indexOf "(" và ")" và sau đó chia những gì ở giữa? Điều đó sẽ tốt hơn là một regex điên? –

+0

@JasonL .: Tôi đã thêm một số mã vào câu trả lời (và một ví dụ trực tiếp). –

+0

Cảm ơn! Giải pháp của bạn đơn giản hơn nhiều so với tôi nghĩ tôi đang mong đợi. Tôi hiện đang thử nó với tất cả các biến thể khác nhau mà javascript cho phép. Điều này sẽ nắm bắt bất kỳ của các ký tự đặc biệt điên javascript cho phép (một trong những nổi tiếng nhất là cái nhìn của sự từ chối)? Tôi cũng nên lưu ý rằng điều này là dành cho môi trường node.js ONLY, vì vậy tôi thực sự chỉ cần lo lắng về V8 :) –

3

Đỗ như sau:

var ar = str.match(/\((.*?)\)/); 
if (ar) { 
    var result = ar[0].split(","); 
} 

Ghi? sau * không một tổ chức phi tham lam tìm

2

Hãy để tôi đề nghị bạn sử dụng biểu thức thông thường:

  • [trận] /function[^(]*\(([^)]*)\)/ sẽ phù hợp với danh sách đối số
  • [split] /\W+/ (so với kết quả của dữ liệu trận đấu đầu tiên) sẽ chia trận đấu vào danh sách params

Vì vậy, các mã sẽ giống như thế này:

var s = "function moo (paramOne, paramTwo) { alert('hello'); }"; 
var s2 = s.match(/function[^(]*\(([^)]*)\)/)[1]; 
var paramList = s2.split(/\W+/); 
+0

Thật tuyệt, công việc tốt 1 – iConnor

Các vấn đề liên quan