2012-11-08 67 views
9

Tôi đã mong JavaScript loại bỏ các đối tượng có thuộc tính trùng lặp là không hợp lệ nhưng nó chấp nhận chúng trong một số trường hợp.Tại sao đối tượng có thuộc tính trùng lặp được chấp nhận trong JavaScript?

{"a":4,"a":5} kết quả trong một ít nhất là trong Firefox và Chrome có vẻ hiển nhiên do thuộc tính a được xác định hai lần.

Tuy nhiên ({"a":4,"a":5}) đánh giá tốt và dẫn đến đối tượng {"a":5} trong cả Firefox và Chrome.

Tại sao biểu thức có dấu ngoặc đơn được chấp nhận?

Tổng hợp các câu trả lời: Ví dụ đầu tiên đơn giản không phải là việc xây dựng một đối tượng mà là một khối các câu lệnh có nhãn. Tính thích hợp trùng lặp trong các đối tượng là hoàn toàn hợp lệ trong trường hợp đó định nghĩa cuối cùng sẽ thắng.

Cảm ơn rất nhiều câu trả lời của bạn!

+1

Dường như làm việc tốt có và không có dấu ngoặc đơn trên FF và Chrome http://jsbin.com/iponud/1/edit. Tôi có nghĩa là nó trả về 'a' – elclanrs

+0

@elclanrs cuối cùng: kết quả đó là gây hiểu nhầm (tôi đã tự viết nó vào jsfiddle trước đó :) - đặt mã trong câu hỏi bên trong danh sách đối số' console.log' loại bỏ [cú pháp sự mơ hồ đã gây ra lỗi ở nơi đầu tiên] (http://stackoverflow.com/a/13287483/1081234) –

Trả lời

3

gì bạn nêu không có vấn đề nếu bạn gán nó vào một biến, nếu bạn không tuy nhiên, bạn nhận được lỗi bạn đề cập đến. Mà làm cho tất cả sự khác biệt từ một điểm cú pháp của xem.

Khi bạn bọc bất kỳ cấu trúc nào khi bạn đang làm cho cú pháp đó được đánh giá dưới dạng một biểu thức, kết quả được lưu trữ dưới dạng biến tạm thời. Lỗi tôi nhận được khi không làm như vậy trong Firefox là nhãn không mong muốn hoặc nhãn không hợp lệ, vì vậy có vẻ như không có nhiệm vụ hoặc parens, xây dựng đối tượng này không được coi là xây dựng đối tượng - thay vào đó nó được coi là một khối có nhiều báo cáo nhãn được định nghĩa bất hợp pháp:

{ 
    a: function(){ 
    alert('a'); 
    }, 
    b: function(){ 
    alert('b'); 
    } 
} 

trên đây nên hoàn toàn có thể chấp nhận như một đối tượng, tuy nhiên bạn nhận được một lỗi tương tự nếu bạn đánh giá nó mà không Cử nó để một số hình thức biến, hoặc đánh giá nó với dấu ngoặc. Đặt chỉ đơn giản là sự trùng lặp của tên thuộc tính không gây ra lỗi :)

Về cơ bản tưởng tượng ví dụ đầu tiên của bạn, nhưng như thế này:

function(){ 
    "a": 4, 
    "b": 5 
} 

Đó là khoảng bao nhiêu những trình duyệt được điều trị nó, mà bây giờ rõ ràng cú pháp javascript bất hợp pháp ... trong khi nó không quá rõ ràng trước đây.

0

Tại sao nó không được chấp nhận? Bạn chỉ đơn giản là ghi đè các giá trị. Tôi nghĩ rằng đó là một tính năng hơn là một lỗi. Và nó hoạt động tốt đối với tôi trên các trình duyệt khác nhau: http://jsbin.com/oculon/1/edit Nó giống như viết

var a; 

a = 4; 
a = 5; 

alert(a); 
4

Đó là hoàn toàn hợp pháp trong ECMAScript 3 kê khai tài sản trùng lặp trong một đối tượng theo nghĩa đen; SyntaxError có thể xuất phát từ thực tế là bạn đã sử dụng một đối tượng theo nghĩa đen như một câu lệnh, điều này là không thể do sự nhầm lẫn với các câu lệnh khối ({ doSomething(); }).

Nếu bạn muốn báo cáo này được báo cáo là lỗi, bạn có thể chuyển sang chế độ nghiêm ngặt của ECMAScript 5: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode.

+0

+1 điểm tốt về chế độ nghiêm ngặt. – Pebbl

+1

Điều thú vị là các tên thuộc tính trùng lặp hoàn toàn ổn định trong chế độ nghiêm ngặt của ECMAScript 6. Mọi người nhận thấy nó là một chút khó khăn để viết literals đối tượng mà không có lỗi cú pháp khi bạn không biết tên tài sản trước. – Robert

0

nó không Lỗi bạn chỉ cần ghi đè lên giá trị với một

0

Tôi đoán (mặc dù không chắc chắn) rằng điều này đánh giá là lỗi vì sự khác biệt giữa cách Firefox và các trình phân tích cú pháp JS của Chrome xử lý các câu lệnh và biểu thức. Vì vậy, bởi vì nó được bọc trong ngoặc đơn lần thứ hai, nó được coi là một biểu thức. Vì nó tìm kiếm ít thông tin hơn trong một biểu thức, nó có thể bỏ qua các giá trị sai lầm. Bạn sẽ thấy rằng nếu bạn làm ...

var a = {'a': 5, 'a': 4}; 
console.log(a); 

Nó hoạt động tốt! Và cũng lưu ý rằng ở đây nó nằm ở phía bên phải của câu lệnh, đưa ra một gợi ý rằng đó là một biểu hiện.

2

Trong ký hiệu đầu tiên (dấu ngoặc đơn) cú pháp javascript không rõ ràng. Từ ecmascript specification:

Một ExpressionStatement không thể bắt đầu với một khe hở xoăn cú đúp vì đó có thể làm cho nó rõ ràng với một Khối.

Một block cơ bản đánh giá tất cả các báo cáo bên trong, tương đương với việc đánh giá "a":4,"a":5 mà không có giá trị JS và, trên thực tế, trả về Lỗi Cú pháp cùng Unexpected token :

Bao bì rằng mã trong ngoặc đơn (hoặc, đúng hơn, a grouping operator) loại bỏ mà mơ hồ từ một biểu thức chuyển nhượng không thể được theo sau bởi một tuyên bố khối:

var test = {"a":"a","a":"b"}; //test.a === "b" 

Hơn nữa sự mơ hồ này có thể được loại bỏ bởi bất kỳ toán tử hoặc biểu thức nào không thể được sử dụng với một câu lệnh khối. Một kịch bản thực tế hầu như không đến với tâm trí, có lẽ nếu bạn muốn trả về một đối tượng theo nghĩa đen như là một phần của toán tử có điều kiện?

//this *could* come out of a JS minifier: 
return x ? (foo(),{"a":"b"}) : (bar(), {"b":"a"}); 
Các vấn đề liên quan