Một chút nền:
ECMAScript 6 + phân biệt giữa callable (có thể được gọi mà không new
) và constructable (có thể được gọi với new
) chức năng:
- Chức năng tạo thông qua cú pháp hàm mũi tên hoặc thông qua định nghĩa phương thức trong các lớp hoặc đối tượng literals là không thể cấu hình được.
- Các hàm được tạo thông qua cú pháp
class
là không gọi được.
- Chức năng được tạo theo bất kỳ cách nào khác (biểu thức/khai báo hàm,
Function
hàm tạo) có thể gọi và có thể cấu hình được.
- Các chức năng tích hợp không được xây dựng trừ khi có quy định rõ ràng khác.
Về Function.prototype
Function.prototype
là một cái gọi là built-in functionthat is not constructable. Từ thông số:
Đối tượng chức năng tích hợp không được xác định là nhà thầu không thực hiện phương thức nội bộ [[Construct]]
trừ khi được chỉ định khác trong mô tả của một chức năng cụ thể.
Giá trị Function.prototype
được tạo ngay từ đầu khởi tạo thời gian chạy. Về cơ bản nó là một hàm rỗng và nó không được tuyên bố rõ ràng rằng nó có thể xây dựng được.
Làm thế nào để kiểm tra xem một chức năng là một nhà xây dựng để nó có thể được gọi với một mới?
Không có cách tích hợp để thực hiện điều đó. Bạn có thể try
để gọi hàm với new
, và một trong hai kiểm tra các lỗi hoặc trả lại true
:
function isConstructor(f) {
try {
new f();
} catch (err) {
// verify err is the expected error and then
return false;
}
return true;
}
Tuy nhiên, cách tiếp cận đó không phải là chạy failsafe từ chức năng có thể có tác dụng phụ, vì vậy sau khi gọi f
, bạn không biết trong đó nêu rõ môi trường.
Ngoài ra, điều này sẽ chỉ cho bạn biết chức năng có thể được gọi là hàm tạo hay không, không phải là được dự định để được gọi là hàm tạo. Cho rằng bạn phải xem tài liệu hoặc việc thực hiện chức năng.
Lưu ý: Không bao giờ có lý do để sử dụng thử nghiệm như thế này trong môi trường sản xuất. Có hay không một chức năng được cho là được gọi với new
nên được nhận thấy rõ ràng từ tài liệu của nó.
Khi tôi tạo hàm, làm cách nào để làm cho hàm KHÔNG phải là hàm tạo?
Để tạo một chức năng thực sự là không constructable, bạn có thể sử dụng một chức năng mũi tên:
var f =() => console.log('no constructable');
chức năng mũi tên là theo định nghĩa không constructable. Hoặc bạn có thể định nghĩa một hàm như là một phương thức của một đối tượng hoặc một lớp.
Nếu không, bạn có thể kiểm tra xem một hàm được gọi với new
(hoặc một cái gì đó tương tự) bằng cách kiểm tra nó this
giá trị và ném ra một lỗi nếu nó là:
function foo() {
if (this instanceof foo) {
throw new Error("Don't call 'foo' with new");
}
}
Tất nhiên, kể từ khi có những cách khác để thiết lập giá trị của this
, có thể có dương tính giả.
Ví dụ
function isConstructor(f) {
try {
new f();
} catch (err) {
if (err.message.indexOf('is not a constructor') >= 0) {
return false;
}
}
return true;
}
function test(f, name) {
console.log(`${name} is constructable: ${isConstructor(f)}`);
}
function foo(){}
test(foo, 'function declaration');
test(function(){}, 'function expression');
test(()=>{}, 'arrow function');
class Foo {}
test(Foo, 'class declaration');
test(class {}, 'class expression');
test({foo(){}}.foo, 'object method');
class Foo2 {
static bar() {}
bar() {}
}
test(Foo2.bar, 'static class method');
test(new Foo2().bar, 'class method');
test(new Function(), 'new Function()');
Thú vị là 'Function' và' Function.prototype' là 'hàm' duy nhất không phải là hàm tạo? – Adam
Chức năng là một construtor. new Function(); công trinh. –
Chỉ cần kiểm tra xem loại có phải là một hàm hay không. – rlemon