Có một số cách khác nhau để gọi một hàm mà không có dấu ngoặc đơn.
Giả sử bạn có chức năng này được xác định:
function greet() {
console.log('hello');
}
Sau đó, ở đây làm theo một số cách để gọi greetmà không có dấu ngoặc đơn:
1. Là người xây dựng
Với newbạn có thể gọi một hàm mà không có dấu ngoặc đơn:
new greet; // parentheses are optional in this construct.
Từ MDN trên newoprator :
Cú pháp
new constructor[([arguments])]
2. Như toStringhoặc valueOfthực hiện
toStringvà valueOflà các phương thức đặc biệt: chúng được gọi ngầm khi cần chuyển đổi:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
Bạn có thể (ab) sử dụng mẫu này để gọi greetmà không có dấu ngoặc đơn:
'' + { toString: greet };
Hoặc với valueOf:
+{ valueOf: greet };
valueOfvà toStringtrên thực tế được gọi từ phương thức @@ toPrimitive (kể từ ES6), và do đó bạn cũng có thể thực hiện phương thức đó :
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b Ghi đè valueOftrong Nguyên mẫu Chức năng
Bạn có thể lấy ý tưởng trước đó để ghi đè valueOfphương thức trên Functionnguyên mẫu :
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
Một khi bạn đã làm điều đó, bạn có thể viết:
+greet;
Và mặc dù có các dấu ngoặc đơn liên quan đến dòng xuống, lời gọi kích hoạt thực tế không có dấu ngoặc đơn. Xem thêm về điều này trong blog "Phương thức gọi bằng JavaScript, mà không thực sự gọi chúng"
3. Là máy phát điện
Bạn có thể định nghĩa một hàm tạo (với *), trả về một trình vòng lặp . Bạn có thể gọi nó bằng cú pháp lây lan hoặc với for...ofcú pháp.
Đầu tiên chúng ta cần một biến thể của greethàm ban đầu :
function* greet_gen() {
console.log('hello');
}
Và sau đó chúng ta gọi nó mà không có dấu ngoặc đơn bằng cách định nghĩa phương thức @@ iterator :
[...{ [Symbol.iterator]: greet_gen }];
Thông thường các trình tạo sẽ có một yieldtừ khóa ở đâu đó, nhưng hàm này không cần thiết để được gọi.
Câu lệnh cuối cùng gọi hàm, nhưng điều đó cũng có thể được thực hiện với hàm hủy :
[,] = { [Symbol.iterator]: greet_gen };
hoặc một for ... ofcấu trúc, nhưng nó có dấu ngoặc đơn của chính nó:
for ({} of { [Symbol.iterator]: greet_gen });
Lưu ý rằng bạn cũng có thể thực hiện các thao tác trên với greetchức năng ban đầu , nhưng nó sẽ kích hoạt một ngoại lệ trong quy trình, sau khi greet đã được thực thi (đã thử nghiệm trên FF và Chrome). Bạn có thể quản lý ngoại lệ với một try...catchkhối.
4. Là Getter
@ jehna1 có câu trả lời đầy đủ về vấn đề này, vì vậy hãy cho anh ta tín dụng. Đây là một cách để gọi một hàm ngoặc đơn trên phạm vi toàn cục, tránh phương thức không dùng nữa__defineGetter__ . Nó sử dụng Object.definePropertythay thế.
Chúng ta cần tạo một biến thể của greetchức năng ban đầu cho việc này:
Object.defineProperty(window, 'greet_get', { get: greet });
Và sau đó:
greet_get;
Thay thế windowbằng bất cứ đối tượng toàn cầu của bạn là gì.
Bạn có thể gọi greethàm ban đầu mà không để lại dấu vết trên đối tượng toàn cầu như thế này:
Object.defineProperty({}, 'greet', { get: greet }).greet;
Nhưng người ta có thể tranh luận rằng chúng ta có dấu ngoặc đơn ở đây (mặc dù chúng không liên quan đến việc gọi thực tế).
5. Chức năng thẻ
Vì ES6, bạn có thể gọi một hàm truyền cho nó một mẫu bằng chữ với cú pháp này:
greet``;
Xem "Tagged Template Literals" .
6. Là Trình xử lý Proxy
Kể từ ES6, bạn có thể xác định proxy :
var proxy = new Proxy({}, { get: greet } );
Và sau đó đọc bất kỳ giá trị tài sản sẽ gọi greet:
proxy._; // even if property not defined, it still triggers greet
Có nhiều biến thể của điều này. Một ví dụ nữa:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7. Trình kiểm tra ví dụ
Các instanceofnhà điều hành thực hiện các @@hasInstancephương pháp trên các toán hạng thứ hai, khi đã xác định:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet