2010-06-14 68 views
181

đối tượng tôi đã thấy được tạo ra theo cách này:Chúng ta có thể bỏ qua dấu ngoặc đơn khi tạo đối tượng bằng toán tử "mới" không?

const obj = new Foo; 

Nhưng tôi nghĩ rằng ngoặc là không bắt buộc khi tạo một đối tượng:

const obj = new Foo(); 

có phải là cách cựu của việc tạo ra đối tượng hợp lệ và quy định tại tiêu chuẩn ECMAScript? Có bất kỳ sự khác biệt nào giữa cách tạo đối tượng cũ và sau này không? Là một trong những ưu tiên hơn khác?

+0

http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.2 – SheetJS

+0

Tham chiếu cập nhật: ECMAScript 2017 [* §12.3.3 Toán tử mới *] (http: // ecma -international.org/ecma-262/8.0/#sec-new-operator). – RobG

Trả lời

192

Trích dẫn David Flanagan :

As a special case, for the new operator only, JavaScript simplifies the grammar by allowing the parenthesis to be omitted if there are no arguments in the function call. Here are some examples using the new operator:

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

... 

Cá nhân, tôi luôn luôn sử dụng dấu ngoặc đơn, ngay cả khi các nhà xây dựng 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 lựa chọn cho công cụ để chịu đựng thiếu sót ngoặc.


David Flanagan: JavaScript the Definitive Guide: 4th Edition (trang 75)

+5

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

+10

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

+11

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) đã yêu cầu họ làm như vậy", đặc biệt là xem xét các ví dụ trên https://developer.mozilla.org/en-US/docs/ Web/JavaScript/Hướng dẫn/Details_of_the_Object_Model, từ "những kẻ đã phát minh ra ngôn ngữ " không sử dụng bất kỳ dấu ngoặc đơn nào trên 'lớp mới' cho các hàm tạo parameterless. Nếu điều này không đánh vần 'có ý kiến', tôi không biết điều gì ... – ack

13

Nếu bạn không có lý lẽ để vượt qua, các dấu ngoặc đơn là không bắt buộc. Bỏ qua chúng chỉ là cú pháp.

+3

Tôi sẽ nói cú pháp, nhưng ymmv. –

5

Không có sự khác biệt giữa hai loại.

14

Tôi không nghĩ có 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ề việc thành thói quen này, như hai dòng mã 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 
+0

Thậm chí còn có vấn đề hơn nếu bạn có thói quen bỏ qua dấu chấm phẩy. ;-) – RobG

5

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-new-operator-runtime-semantics-evaluation

Đây là một phần của spec ES6 định nghĩa như thế nào hai biến thể hoạt động. Biến thể không có dấu ngoặc đơn chuyển 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 
+0

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

+0

http://es5.github.io/x11.html#x11.2.2 đây là liên kết dành cho ES5 – guest

41

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

  • new Date().toString() công trình hoàn hảo và trả về ngày hiện tại
  • new Date.toString() ném "Lỗi Loại: Date.toString không phải là một constructor"

Điều này xảy ra vì new Date()new Date ha đã ưu tiên khác nhau.Theo MDN phần của JavaScript bảng điều hành ưu tiên chúng tôi quan tâm đến vẻ bề ngoài 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 sau đó:

  1. new Foo() có độ ưu tiên cao hơn sau đó new Foo

    new Foo() có cùng một ưu tiên như . nhà điều hành

    new Foo có độ ưu tiên một cấp thấp hơn thì . hành

    new Date().toString() công trình một cách hoàn hảo bởi vì nó đánh giá như (new Date()).toString()

    new Date.toString() ném "Lỗi Loại: Date.toString không phải là một constructor" vì . có độ ưu tiên cao hơn sau đó new Date (và cao hơn thì "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 Footừ phải sang trái kết hợp và cho new Foo() "liên kết" không áp dụng được. Tôi nghĩ trong thực tế nó không tạo ra bất kỳ sự khác biệt nào. Để biết thêm thông tin, xem this SO câu hỏi


Is one preferred over the other?

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

+1

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

+0

wow, cảm ơn. nhắc tôi về một ngôn ngữ khác https://en.wikipedia.org/wiki/Brainfuck –

+0

Cũng giải thích, 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ác vấn đề liên quan