2014-09-09 17 views
5

Tôi có một hàm nhất định, trong số các đối số khác, hai đối số tùy chọn có thể là các hàm. Cả hai cần phải là tùy chọn, một sẽ là một hàm, và một sẽ là một boolean hoặc một hàm trả về một boolean.Kiểm tra xem hàm JavaScript có trả về mà không thực thi không?

// Obj.func(variable, String[, Object][, Boolean||Function][, Function]); 
Obj.func = function(other, assorted, args, BoolOrFunc, SecondFunc) { 
    // execution 
}; 

Obj.func(
    [ 
     'some', 
     'data' 
    ], 
    'of varying types', 
    { 
     and: 'some optional arguments' 
    }, 
    function() { 
     if(some condition) { 
      return true; 
     } 
     return false; 
    }, 
    function() { 
     // do things without returning 
    } 
); 

Đó là mong muốn của tôi mà cả hai chức năng (và một số trong những lập luận khác, nếu vấn đề) là tùy chọn, có nghĩa là tôi có mã trong hàm để xác định tham số người dùng có ý định sử dụng.

Thật không may, vì cả hai có thể có chức năng và có thể được chỉ định trực tiếp trong cuộc gọi chức năng, tôi không thể sử dụng đơn giản là typeof hoặc instanceof điều kiện. Tuy nhiên, kể từ khi chức năng đầu tiên, nếu nó tồn tại, sẽ luôn trả về một boolean (và chức năng thứ hai sẽ không trở lại tại tất cả), một trong những ý tưởng tôi đã sẽ được kiểm tra giá trị trả về của nó:

if(typeof BoolOrFunc === 'boolean' 
    || (typeof BoolOrFunc === 'function' && typeof BoolOrFunc() === 'boolean')) { 
    // BoolOrFunc is either a boolean or a function that returns a boolean. 
    // Handle it as the intended argument. 
} else { 
    // Otherwise, assume value passed as BoolOrFunc is actually SecondFunc, 
    // and BoolOrFunc is undefined. 
} 

này hoạt động theo nguyên tắc; tuy nhiên, chạy typeof BoolOrFunc() thực thi hàm, gây ra sự cố nếu hàm không chỉ trả về boolean: tức là, nếu hàm được chuyển thành BoolOrFuncthực tế là có nghĩa là SecondFunc. SecondFunc, trong trường hợp này, là một chức năng gọi lại và có thể thực hiện các hành động, bao gồm sửa đổi DOM, mà tôi không muốn thực thi ngay lập tức.

Vì lý do này, câu hỏi của tôi là: Có cách nào để kiểm tra xem một hàm có trả về mà không thực thi không?

Một điều tôi đã coi là để gọi BoolOrFunc.toString(), sau đó thực hiện tìm kiếm Regular Expression cho giá trị trả về, một cái gì đó dọc theo dòng của ...

if(typeof BoolOrFunc === 'boolean' 
    || (typeof BoolOrFunc === 'function' 
     && BoolOrFunc.toString().search(/return (true|false);/) !== -1)) { 
    // BoolOrFunc is either a boolean or contains a return string with a boolean. 
    // Handle it as the intended argument. 
} 

Lưu ý rằng mã trên có thể không làm việc như viết: Tôi đã không thực sự xây dựng một trường hợp thử nghiệm cho nó, bởi vì, tốt, nó có vẻ đặc biệt không hiệu quả và có khả năng không đáng tin cậy, và tôi đã tìm một ai đó ở đây có thể có một giải pháp thanh lịch hơn cho tình trạng khó khăn của tôi. Điều đó đã được nói, tôi figured tôi muốn bao gồm nó cho các mục đích thảo luận.

+1

Là một lưu ý giai thoại, điều này là khá gần với các vấn đề dừng (http://en.wikipedia.org/wiki/Halting_problem) mà là undecidable trên máy Turing. :) – lexicore

+0

Heh, bạn đưa ra một điểm tốt. Tôi có thể mong đợi quá nhiều từ JS. : P – Meshaal

+0

Đối với trường hợp người dùng gọi biểu mẫu cung cấp boolean và hàm trả về boolean, bạn có thể yêu cầu thay vào đó họ chuyển vào đối số được bao bọc trong một đối tượng, ví dụ: 'Obj.func (myvar, mystring, myobj, {boolarg: true, funcarg: my_func_that_returns_bool}); 'hoặc một cái gì đó tương tự, để làm cho nó rõ ràng nó là gì. Sau đó, người dùng phải đảm bảo rằng 'my_func_that_returns_bool' thực hiện khi xác nhận quyền sở hữu – Brandin

Trả lời

1

Meshaal đã dự đoán trong câu hỏi:

"... one will either be a boolean or a function that returns a boolean." 
"... first function, if it exists, will always return a boolean." 

Với dự đoán này chức năng không phải là một máy Turing, bởi vì chúng ta biết rằng nó sẽ trả về một cái gì đó. Chắc chắn nó không thể được thực hiện với một RegExp đơn giản: chỉ cần return !0 sẽ phá vỡ ví dụ.

Nhưng nếu bạn phân tích cú pháp kết quả của hàm.toString() với trình phân tích cú pháp đủ thông minh để tìm tất cả các điểm trả về có thể, vấn đề chủ yếu nên được giải quyết.

0

Câu hỏi thú vị, nếu tôi hiểu chính xác. Đầu tiên, tôi có thể cảnh báo chống lại các đối số mở như vậy. Tôi rất tò mò về trường hợp sử dụng.

Nhưng điều đó nói rằng, thật dễ dàng để giải quyết các vấn đề bạn đề cập (có thể không giải quyết được hoàn toàn vấn đề của bạn).

Điều này hoạt động theo nguyên tắc; tuy nhiên, chạy typeof BoolOrFunc() thực thi hàm ...

Thật dễ dàng, đủ để khắc phục, tôi nghĩ vậy. Lúc đầu, chỉ cần kiểm tra xem nếu BoolOrFunc là một boolean hoặc một hàm (chỉ cần typeof BoolOrFunc, natch). Nếu đó là một boolean, tôi cho rằng chúng ta ổn. Thiếu SecondFunc (undefined) hoặc function - hoặc chúng tôi đang ở trạng thái lỗi. Đó là tất cả dễ dàng để xử lý trong trường hợp đầu tiên này.

Vì vậy, hãy giả sử trường hợp thứ hai, chúng tôi có BoolOrFunc-As-Function. Chúng tôi sẽ phải thực hiện nó, cho dù đó là "thực sự" BoolOrFunchoặcSecondFunc, vì vậy, tại thời điểm cuối cùng có thể trong mã của bạn, hãy làm như vậy.

Điều này rõ ràng là nơi mọi thứ trở nên phức tạp mà không cần thêm mã giả (hoặc mã sản xuất) từ bạn. Nếu "có thể BoolOrFunc" trả lại true hoặc false, bạn biết mình có phiên bản chức năng là BoolOrFunc. Nếu nó trả về undefined, bạn biết bạn chỉ cần gọi là SecondFunc. Một lần nữa, tùy thuộc vào những gì bạn đang cố gắng để làm, bạn chi nhánh ở đây. Nếu bạn có true hoặc false, bạn phải xử lý "BoolOrFunc-as-function", nếu không bạn đã gọi SecondFunc và có thể đã hoàn tất.

Điều đó không trả lời câu hỏi chung chung hơn về cách cho biết hàm trả về một loại cụ thể mà không gọi nó, nhưng giải quyết trường hợp sử dụng của bạn như được trình bày ở đây.

Nhưng trường hợp cụ thể hơn chung này [sic] không quá khó, miễn là chúng tôi đang xử lý thực, hằng số booleans trong số return s. Trong trường hợp đó, tuyến đường regexp sẽ hoạt động - tìm tất cả return\s+.*; và đảm bảo những gì sau mỗi returntrue hoặc false. Hoặc chỉ cần so sánh tổng số lượt truy cập return tương tự như số return\s+(false|true);. Hoặc một cái gì đó. Và hy vọng javascript trong hàm cũng được hình thành. Thật là một con gấu rồi.

Nếu chức năng có thể trả về biến cục bộ (return MightBeBoolean;), bạn gần như bánh mì nướng - hoặc nếu bạn chấp nhận sự thật hoặc giả mạo, bạn gần như nướng bánh mì, vì undefined là falsey, và bạn không thể cho biết sự khác biệt giữa BoolOrFunc hoặc SecondFunc (sẽ luôn trả về "falsey"). Có thể, nhưng gần như không đáng viết bộ phân tích cú pháp trong bất kỳ trường hợp sử dụng hợp lý nào tôi có thể tưởng tượng. Và nếu bạn đang nhập một lib để làm điều đó, sheesh. Chúc may mắn. Có vẻ như quá mức cần thiết để có chức năng phòng thủ hơn một chút trong cuộc gọi của nó.

Tôi tự hỏi liệu một trong hai hàm có được truyền dưới dạng đối số hay không là chúng đã chuyển đối số từ Obj.func của bạn, điều này sẽ làm cho mọi thứ trở nên thú vị hơn.

Bạn có thêm mã thực? ; ^) Nhưng cuối cùng tôi đề nghị bạn không làm "vượt qua bất kỳ sự lộn xộn của các đối số, miễn là họ đang theo thứ tự". Tôi nghĩ rằng bạn có thể làm việc đánh giá trễ BoolOrFunc/SecondFunc. Nếu không, tôi ghét phải nói điều đó, nhưng mã hơn một chút của số ở đây.

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