Nó phụ thuộc vào nơi và cách chức năng là (hoặc không) tuyên bố.
Nếu đó là một toàn cầu và không khai báo qua let name = ...
hoặc const name = ...
cú pháp (và nó không phải là một constructor lớp khai báo với class
), bạn có thể kiểm tra bằng cách tìm kiếm nó như là một tài sản trên các đối tượng toàn cầu. (Những cảnh báo đó là tất cả những thứ ES2015; dưới đây.) Bạn có thể lấy một tham chiếu đến đối tượng toàn cầu qua this
ở chế độ lỏng lẻo ở phạm vi toàn cầu; các trình duyệt cũng cung cấp cho bạn toàn cầu được gọi là window
. Vì vậy, giả sử một trình duyệt:
if (typeof window[func_name] === "function") {
// ....
}
Nếu nó có thể không là một toàn cầu, nhưng thay vì chỉ là trong phạm vi bởi vì mã của bạn đóng trên nó, hoặc nếu nó được tạo bằng một trong những cơ chế ES2015 tôi đã đề cập, có thực sự không có cách nào tốt để kiểm tra khác hơn eval
:
if (eval("typeof " + func_name) === "function") {
// ....
}
sử dụng eval
là một phương sách cuối cùng, và bạn phải chỉ sử dụng nó với đầu vào nghiêm ngặt kiểm soát. Nhưng khi bạn phải làm thế, và bạn có đầu vào được kiểm soát chặt chẽ, điều đó là tốt.
Về hãy cẩn thận ES2015:
mới let
, const
, và class
là beasties rất thú vị: Khi sử dụng ở phạm vi toàn cầu, họ tạo globals, nhưng họ không tạo thuộc tính trên đối tượng toàn cầu. Kể từ ES2015, mặc dù tất cả các thuộc tính của đối tượng chung là các hình cầu, nhưng không phải tất cả các thuộc tính đều là các thuộc tính của đối tượng chung. Đó là một phần của việc cố gắng kiềm chế trong không gian tên toàn cầu bị ô nhiễm và cũng mang lại sự bảo mật cao hơn cho mô hình ràng buộc JavaScript. (Bây giờ chúng ta có các mô-đun thực sự.)
Vì vậy, (lưu ý rằng điều này sẽ chỉ chạy trong các trình duyệt tiên tiến):
// Global scope, in a browser (because I used `window` and `document.body`) that
// implements this aspect of ES2015 (as I write this, Firefox's SpiderMonkey
// doesn't, Chrome's V8 does on the latest Chrome; expect SpiderMonkey and IE
// to catch up pretty quick (didn't test IE Edge, maybe it's already there)
// Strict mode isn't required for this behavior, but for the moment V8 only
// supports the block-scoped constructs in strict mode.
"use strict";
let tbody = setup();
// Old-fashioned var: Creates a property on the global object, so
// we get "function, function"
var f1 = function() { /*...*/ };
result("var declaration", typeof f1, typeof window["f1"]);
// Function declaration: Creates a property on the global object, so
// "function, function"
function f2() {}
result("function declaration", typeof f2, typeof window["f2"]);
// `let` declaration: Doesn't create property on global object, so
// "function, undefined"
let f3 = function() { /*...*/ };
result("let declaration", typeof f3, typeof window["f3"]);
// `const` declaration: Doesn't create property on global object, so
// "function, undefined"
const f4 = function() { /*...*/ };
result("const declaration", typeof f4, typeof window["f4"]);
// `class` declaration: Doesn't create property on global object, so
// "function, undefined"
class C1 {}
result("class declaration", typeof C1, typeof window["C1"]);
function setup() {
document.body.insertAdjacentHTML(
"beforeend",
"<table>" +
"<thead>" +
"<tr><th>test</th><th>global</th><th>prop</th></tr>" +
"</thead>" +
"<tbody></tbody>" +
"</table>"
);
return document.body.querySelector("tbody");
}
function result(label, direct, win) {
tbody.insertAdjacentHTML(
"beforeend",
"<tr><td>" + [label, direct, win].join("</td><td>") + "</td></tr>"
);
}
body {
font-family: sans-serif;
}
table {
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 4px 8px;
}
Output trên các trình duyệt tiên tiến:
+----------------------+------------+-----------+
| test | global | prop |
+----------------------+------------+-----------+
| var declaration | function | function |
| function declaration | function | function |
| let declaration | function | undefined |
| const declaration | function | undefined |
| class declaration | function | undefined |
+----------------------+------------+-----------+
Lưu ý: Một số transpilers không thực thi điều này một cách nghiêm ngặt, vì vậy nếu bạn thấy các kết quả khác nhau trong mã transpiled, đừng ngạc nhiên.
Để vượt qua đối số: cửa sổ [FUNC_NAME] (myArg1, myArg2); – mpemburn