Tại sao kết quả thay đổi dựa trên vị trí dấu ngoặc nhọn?


119

Tại sao các đoạn mã dưới đây, được lấy từ bài viết này , lại tạo ra các kết quả khác nhau do chỉ một thay đổi duy nhất về vị trí của các dấu ngoặc nhọn?

Khi dấu ngoặc nhọn mở {trên một dòng mới, test()trả về undefinedvà "no - it break: undefined" được hiển thị trong cảnh báo.

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Khi dấu ngoặc nhọn trên cùng dòng với return, test()trả về một đối tượng và "tuyệt vời" được cảnh báo.

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}


ngữ nghĩa của dấu bán chèn sau returnhơi khác so với những nơi khác và dấu ngắt dòng "có nghĩa là nhiều hơn" ở chỗ đó hơn là "giữa dòng".
dandavis

Câu trả lời:


165

Đó là một trong những cạm bẫy của JavaScript: tự động chèn dấu chấm phẩy. Các dòng không kết thúc bằng dấu chấm phẩy, nhưng có thể là cuối câu lệnh, sẽ tự động kết thúc, vì vậy ví dụ đầu tiên của bạn trông giống như sau:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

Xem thêm hướng dẫn kiểu JS của Douglas Crockford , đề cập đến việc chèn dấu chấm phẩy.

Trong ví dụ thứ hai, bạn trả về một đối tượng (được tạo bởi dấu ngoặc nhọn) với thuộc tính javascriptvà giá trị của nó "fantastic", thực sự giống như sau:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}

5
Fun Fact: Trên một số công cụ bạn có thể nhận xét ra các dấu chấm phẩy tự động chèn
Christopher Tarquini

1
@ChrisT: Cái gì? Những cái nào? Điều này có được khám phá ở bất cứ đâu không?
Sean McMillan

1
@SeanMcMillan Tôi đã xác định đọc các bài báo về nó nhưng dường như không thể tìm thấy bất kỳ bài báo nào trong số chúng từ một tìm kiếm nhanh. Tôi nhớ rằng việc đặt return /*và sau đó */{ sẽ nhận xét hiệu quả dấu chấm phẩy ẩn trong các phiên bản chrome cũ hơn. Không chắc liệu điều đó có còn áp dụng hay không
Christopher Tarquini

2
Vì những điều kỳ quặc này mà tôi đã tự hứa với mình 10 năm trước: tránh xa web! Tôi đã cầu nguyện rằng Interwebs sẽ biến mất ... Thật không may, nó không diễn ra như kế hoạch, và bây giờ tôi cũng phải vật lộn với những vấn đề này. Karma là ab * tch :)
Jowen

1
Tôi đã thấy những người chống lại dấu chấm phẩy trong JavaScript một cách tôn giáo, tôi luôn tự hỏi họ sẽ làm gì với khoảng thời gian thừa đó mà họ tiết kiệm được bằng cách không đặt dấu chấm phẩy.
Iman Mohamadi

9

Javascript không yêu cầu dấu chấm phẩy ở cuối câu lệnh, nhưng hạn chế là nó phải đoán vị trí của dấu chấm phẩy. Hầu hết thời gian đây không phải là một vấn đề, nhưng đôi khi nó phát minh ra một dấu chấm phẩy mà bạn không có ý định.

Một ví dụ từ bài đăng trên blog của tôi về điều này ( Javascript - hầu như không dựa trên dòng ):

Nếu bạn định dạng mã như thế này:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

Sau đó, nó được hiểu như thế này:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

Câu lệnh trả về có dạng không tham số và đối số trở thành một câu lệnh của riêng nó.

Điều tương tự cũng xảy ra với mã của bạn. Hàm được hiểu là:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}

3

Cá nhân tôi thích Phong cách Allman hơn vì dễ đọc (so với phong cách K&R).

Thay vì…

function test() {
  return {
    javascript : "fantastic"
  };
}

Tôi thích…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

Nhưng đây là một công việc xung quanh. Tôi có thể sống với nó mặc dù.


3
Tôi nghĩ chúng ta nên tránh những sở thích cá nhân đi chệch khỏi xu hướng chủ đạo. Chúng ta nên làm theo sự lựa chọn của đa số, trong đó khuyến khích sự nhất quán, mà sẽ tăng khả năng đọc
Jowen

1
Tôi thấy mã của anh ấy dễ đọc hơn K&R. Khá chủ quan khi bạn có nghĩa là "có thể đọc được"
Bran

Tôi cũng thích Allman hơn ... nhưng do ASI, khi tôi cần trả lại một đối tượng, tôi để bán phần trên cùng dòng với trả về. Tôi thích điều này hơn là thêm một dòng "var x =" ...
Mik

1

Đó là bởi vì javascript thường đặt ";" ở cuối mỗi dòng, vì vậy về cơ bản khi bạn trả về {trong cùng một dòng, công cụ javascript thấy rằng sẽ có thêm thứ gì đó và khi ở dòng mới, nó nghĩ rằng bạn đã quên đặt ";" và đặt nó cho bạn.


1
Tôi không hiểu tại sao câu trả lời của cichy, Darin và Ivo lại bị từ chối?
BoltClock

1

Dấu ngoặc nhọn ở đây cho biết cấu trúc của một đối tượng mới. Do đó, mã của bạn tương đương với:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

hoạt động trong khi nếu bạn viết:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

nó không còn hoạt động.


0

Vấn đề thực sự là tiêm dấu chấm phẩy như đã mô tả ở trên. Tôi vừa đọc một bài blog tốt về chủ đề này. Nó giải thích vấn đề này và nhiều hơn nữa về javascript. Nó cũng chứa một số tài liệu tham khảo tốt. Bạn có thể đọc nó ở đây


Vâng, tôi cũng đã đọc điều đó, lúc đọc tôi yêu cầu ở đây để giải thích tốt hơn bởi chủ mưu của js.
JustLearn
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.