Chúng ta có thể bỏ qua dấu ngoặc đơn khi tạo một đối tượng bằng cách sử dụng toán tử mới của Wap không?


229

Tôi đã thấy các đối tượng được tạo ra theo cách này:

const obj = new Foo;

Nhưng tôi nghĩ rằng dấu ngoặc đơn không phải là tùy chọn khi tạo đối tượng:

const obj = new Foo();

Là cách trước đây để tạo các đối tượng hợp lệ và được xác định trong tiêu chuẩn ECMAScript? Có sự khác biệt nào giữa cách tạo đối tượng trước đây và sau này không? Là một trong những ưa thích hơn khác?



Tham khảo cập nhật: ECMAScript 2017 §12.3.3 Toán tử mới .
RobG

TL; DR: Hãy coi chừng đó new a.b()là khác nhau từ new a().b(), trong đó, trong trường hợp thứ nhất, a.blà lần đầu tiên truy cập, trong khi ở trường hợp sau, một mới ađược tạo ra đầu tiên.
Andrew

Câu trả lời:


238

Trích dẫn David Flanagan 1 :

Trong trường hợp đặc biệt, chỉ dành cho newtoán tử, JavaScript đơn giản hóa ngữ pháp bằng cách cho phép bỏ dấu ngoặc đơn nếu không có đối số trong lệnh gọi hàm. Dưới đây là một số ví dụ sử dụng newtoán tử:

o = new Object;  // Optional parenthesis omitted here
d = new Date();  

...

Cá nhân, tôi luôn sử dụng dấu ngoặc đơn, ngay cả khi hàm tạo không có đối số.

Ngoài ra, JSLint có thể làm tổn thương cảm xúc của bạn nếu bạn bỏ qua dấu ngoặc đơn. Nó báo cáo Missing '()' invoking a constructor, và dường như không có một tùy chọn nào cho công cụ để chịu đựng thiếu sót trong ngoặc đơn.


1 David Flanagan: JavaScript Hướng dẫn dứt khoát: Phiên bản thứ 4 (trang 75)


6
Tại sao JSLint khuyến khích sử dụng dấu ngoặc đơn?
Randomblue

11
Tôi đoán nó chỉ được coi là phù hợp hơn.
Daniel Vassallo

12
Tôi thấy thú vị khi thấy rằng nhiều nhà phát triển JavaScript sử dụng dấu ngoặc đơn giản chỉ vì "công cụ (JSLint) đã bảo họ làm như vậy", đặc biệt là xem xét các ví dụ trên developer.mozilla.org/en-US/docs/Web/JavaScript/Guide / Lọ , từ "những kẻ đã phát minh ra ngôn ngữ <expletive>" không sử dụng bất kỳ dấu ngoặc đơn nào new Classcho các hàm tạo không tham số. Nếu điều này không đánh vần 'ý kiến', tôi không biết điều gì ...
ack

52
@ack Vâng, sẽ thật kỳ quặc khi không thấy các nhà phát minh ngôn ngữ thể hiện một số tính năng nhất định của ngôn ngữ của họ (trong trường hợp này là tùy chọn bỏ qua dấu ngoặc đơn trên các hàm tạo). Nếu họ không thêm tính năng này, chúng tôi sẽ không hỏi liệu nó có nên được sử dụng ở nơi đầu tiên không. Một lý do thực tế cho việc không sử dụng nó là: new Object.func()KHÔNG tương đương với new Object().func(). Bằng cách luôn luôn bao gồm dấu ngoặc đơn, khả năng phạm sai lầm này được loại bỏ.
nmclean

2
Nếu bạn muốn loại bỏ khả năng mắc lỗi, bạn nên sử dụng (new Object).func(). Nhưng tôi xem xét việc sử dụng dấu ngoặc đơn bổ sung và các dấu bằng bằng nhau, như trong ==vs ===, một lý do tồi cho việc không học ngôn ngữ của bạn.
Jean Vincent

78

Có sự khác biệt giữa hai:

  • new Date().toString() hoạt động hoàn hảo và trả về ngày hiện tại
  • new Date.toString()ném " TypeError: Date.toString không phải là hàm tạo "

Nó xảy ra bởi vì new Date()new Datecó quyền ưu tiên khác nhau. Theo MDN , một phần của bảng ưu tiên toán tử JavaScript mà chúng ta quan tâm trông giống như:

╔════════════╦═════════════════════════════╦═══════════════╦═════════════╗
 Precedence         Operator type         Associativity   Operators  
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
     18      Member Access                left-to-right   .        
             Computed Member Access       left-to-right    [  ]    
             new (with argument list)     n/a            new  (  ) 
╠════════════╬═════════════════════════════╬═══════════════╬═════════════╣
     17      Function Call                left-to-right   (  )     
             new (without argument list)  right-to-left  new        
╚════════════╩═════════════════════════════╩═══════════════╩═════════════╝

Từ bảng này theo sau:

  1. new Foo() có quyền ưu tiên cao hơn new Foo

    new Foo()có quyền ưu tiên như .toán tử

    new Foocó một mức độ ưu tiên thấp hơn so với .toán tử

    new Date().toString() hoạt động hoàn hảo bởi vì nó đánh giá là (new Date()).toString()

    new Date.toString()ném " TypeError: Date.toString không phải là hàm tạo " vì .có độ ưu tiên cao hơn new Date(và cao hơn là "Gọi hàm") và biểu thức đánh giá là(new (Date.toString))()

    Logic tương tự có thể được áp dụng cho … [ … ]toán tử.

  2. new Foocó tính kết hợp từ phải sang trái và đối với new Foo()"tính kết hợp" không được áp dụng. Tôi nghĩ rằng trong thực tế nó không làm cho bất kỳ sự khác biệt. Để biết thêm thông tin, xem câu hỏi SO này


Là một trong những ưa thích hơn khác?

Biết tất cả những điều đó, có thể giả định rằng nó new Foo()được ưa thích.


4
Cuối cùng, một người thực sự trả lời câu hỏi và chỉ ra sự khác biệt tinh tế!
gcampbell

Ồ cảm ơn nhé. làm tôi nhớ đến một ngôn ngữ khác en.wikipedia.org/wiki/Brainfuck
John Henckel

Giải thích tốt, cung cấp chính xác lý do tại sao new Foo()nên được ưa thích hơn new Foo. Câu trả lời tốt nhất cho đến nay.
CodeLama

Câu trả lời tuyệt vời, bảng ưu tiên và giải thích kèm theo làm cho nó hoàn toàn rõ ràng. Vui mừng bạn giải thích làm thế nào mà làm cho nó tốt để viết new Object().something()cũng như (new Object()).something().
LittleTiger

1
Giải thích tuyệt vời nhưng tôi không đồng ý với kết luận và vẫn nghĩ không sử dụng dấu ngoặc đơn là tốt nếu bạn biết ngôn ngữ của mình. BTW nếu bạn không biết mức độ ưu tiên của JS, bạn cũng có thể sử dụng (new Date).toString(), cùng số lượng ký tự và rõ ràng hơn new Date().toString.
Jean Vincent

14

Tôi không nghĩ có bất kỳ sự khác biệt nào khi bạn sử dụng toán tử "mới". Hãy cẩn thận về thói quen này, vì hai dòng mã này KHÔNG giống nhau:

var someVar = myFunc; // this assigns the function myFunc to someVar
var someOtherVar = myFunc(); // this executes myFunc and assigns the returned value to someOtherVar

1
Thậm chí còn rắc rối hơn nếu bạn có thói quen bỏ dấu chấm phẩy. ;-)
RobG

13

Nếu bạn không có đối số để vượt qua, dấu ngoặc đơn là tùy chọn. Bỏ qua chúng chỉ là cú pháp đường.


8
Tôi sẽ nói cú pháp muối, nhưng ymmv.
Thomas Eding

Tôi sẽ nói thêm chúng nếu chúng không cần thiết là đường cú pháp. :)
Cozzbie

8

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-new-operator-racer-semantics-ev Assessment

Đây là một phần của thông số ES6 xác định cách hai biến thể hoạt động. Biến thể không có dấu ngoặc đơn vượt qua một danh sách đối số trống.

Thật thú vị, hai hình thức có ý nghĩa ngữ pháp khác nhau. Điều này xuất hiện khi bạn cố gắng truy cập một thành viên của kết quả.

new Array.length // fails because Array.length is the number 1, not a constructor
new Array().length // 0

Nó cũng được định nghĩa tốt trong ES5 và ES3 - "Trả về kết quả của việc gọi phương thức nội bộ [[Xây dựng]] trên hàm tạo, không cung cấp đối số (nghĩa là danh sách đối số trống)."
Benjamin Gruenbaum

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.