2012-05-17 24 views
15

Tôi không hiểu tại sao, ở chế độ nghiêm ngặt, lỗi cú pháp xảy ra khi delete được sử dụng trên số nhận dạng không đủ điều kiện.Động cơ đằng sau lỗi cú pháp chế độ nghiêm ngặt khi xóa số nhận dạng không đủ tiêu chuẩn?

Trong hầu hết các trường hợp, có nghĩa là ... nếu bạn khai báo biến theo cách thông thường với từ khóa var, và sau đó cố gắng sử dụng delete trên chúng, ở chế độ không nghiêm ngặt, nó sẽ tự động không thành công ý nghĩa cho chế độ nghiêm ngặt thất bại với một lỗi trong những trường hợp đó.

Tuy nhiên, có những trường hợp bạn không thể xóa định rằng trình độ:

(function() { 

    // "use strict"; 

    var obj = Object.create({}, { bloop: { configurable: false } }); 

    delete obj.bloop; // throws TypeError in strict mode, silently fails in non-strict. 

    console.log('bloop' in obj); // true 

}()); 

chế độ nghiêm ngặt phải làm một kiểm tra thời gian chạy ở đây, bởi vì một TypeError được ném khi điều này là gặp phải. Ngoài ra còn có những trường hợp bạn thể thành công xóa định không đủ tiêu chuẩn trong chế độ không nghiêm ngặt ...

// "use strict"; 

window.bar = 6; 

console.log(typeof bar); // number 

delete bar; // works in non-strict, syntax error in strict! 

console.log(typeof bar); // undefined 

Trong thực tế, sự hiểu biết của tôi, hay không, bạn có thể xóa mọi thứ (trong chế độ không nghiêm ngặt) phụ thuộc trên thuộc tính nội bộ [[Configurable]] và không liên quan gì đến các số nhận dạng đủ điều kiện. Theo như tôi có thể nói, không có cách nào trong chế độ nghiêm ngặt để xóa các đại lượng không toàn cầu (như tính chất của VO địa phương) cấu hình:

(function() { 

    // "use strict"; 

    eval('var foo = 5;'); 

    console.log(typeof foo); // number 

    delete foo; // works in non-strict, SyntaxError in strict. 

    console.log(typeof foo); // undefined 

}()); 

Vì vậy, câu hỏi của tôi là, điểm là những gì of throwing a SyntaxError khi sử dụng delete trên một định danh không đủ tiêu chuẩn, khi TypeError sẽ ném anyway nếu thuộc tính không cấu hình được? Điều này có vẻ như một hạn chế không cần thiết, và trong một số trường hợp dường như không có bất kỳ giải pháp nào khác ngoài việc không sử dụng chế độ nghiêm ngặt (ví dụ thứ ba). Bất cứ ai có thể giải thích động cơ đằng sau quyết định này?


Cập nhật: Tôi chỉ nhận ra rằng tôi đã nhìn ra thực tế là trực tiếp eval cuộc gọi có phạm vi riêng của họ trong chế độ nghiêm ngặt, thay vì phạm vi chức năng gọi điện thoại, vì vậy trong ví dụ thứ ba foo sẽ không được xác định theo chế độ nghiêm ngặt . Dù sao, kiểm tra thời gian chạy vẫn sẽ bắt được điều này, nhưng nó đặt ra một câu hỏi phụ: Không có cách nào để có các biến cục bộ có thể cấu hình ở chế độ nghiêm ngặt, như chúng ta thực hiện với khai báo biến không phải là nghiêm ngặt của eval? AFAIK là một trong số ít sử dụng hợp pháp của eval.

+0

Chính xác những gì bạn có ý nghĩa bởi "(un) định đủ điều kiện"? Tôi không thể tìm thấy thuật ngữ đó trong thông số kỹ thuật. – user123444555621

+1

@ Pumbaa80 một số nhận dạng không có dấu chấm trong đó. :) –

+0

@ Pumbaa80 '(function() {" sử dụng nghiêm ngặt "; var foo; delete foo;}())' ... chromium: 'SyntaxError: Xóa số nhận dạng không đủ tiêu chuẩn ở chế độ nghiêm ngặt.' –

Trả lời

6

Bạn đang nói về Section 11.4.1, paragraph 5.a. của thông số kỹ thuật:

  1. Else, ref is a Reference to an Environment Record binding, so
    a. If IsStrictReference(ref) is true, throw a SyntaxError exception.
    b. Let bindings be GetBase(ref).
    c. Return the result of calling the DeleteBinding concrete method of bindings, providing GetReferencedName(ref) as the argument.

Những gì bạn gọi là "định danh không đủ tiêu chuẩn" được chính thức đặt tên là "Ghi Môi trường ràng buộc".

Bây giờ, cho câu hỏi của bạn. Tại sao lại ném SyntaxError khi 5.c. sẽ thất bại không? Tôi nghĩ bạn đã tự trả lời!

Strict mode must do a runtime check here, because a TypeError is thrown when this is encountered.

Đúng vậy. Nhưng nó luôn luôn tốt hơn để thất bại nhanh chóng. Vì vậy, khi có cơ hội phát hiện Cú pháp Cú pháp (tại thời gian phân tích), cơ hội đó sẽ được thực hiện.

Tại sao? Nó giúp bạn tiết kiệm rắc rối khi sửa ứng dụng của bạn nếu xảy ra lỗi. Hãy suy nghĩ về các IDE có thể hiển thị cho bạn lỗi ngay lập tức, trái với giờ gỡ lỗi.
Ngoài ra, các hạn chế này có thể có lợi cho các trình biên dịch JIT được tối ưu hóa.

+0

Cảm ơn bạn đã đào lên tham chiếu đó. Nó làm cho tinh thần để nghĩ về nó như là một trợ lý gỡ lỗi hoặc tối ưu hóa JIT. Nếu nó được sử dụng như thế, tôi đoán nó có giá trị sự cân bằng của việc không thể xóa những thứ bạn có thể khác. –

2

Nếu bạn muốn xóa đối tượng ở chế độ nghiêm ngặt. Bạn phải đề cập rõ ràng về quyền truy cập thuộc tính. Cũng lưu ý rằng, cách bạn gọi hàm là quan trọng. Nếu toán tử new không được sử dụng this không được xác định theo use strict và bạn không thể sử dụng phương thức bên dưới. Ví dụ:

 
'use strict' 
function func(){ 
    var self = this; 
    self.obj = {}; 
    self.obj.x = 'y' 

    console.log(self.obj); 
    delete self.obj // works 
    // delete obj // doesn't work 
    console.log(self.obj); 
} 

var f = new func(); 

Đối xóa đối tượng bên ngoài của hàm (đóng cửa), bạn sẽ phải gọi như

 
// same code as above 
delete f.obj 
+0

Tôi không chắc điểm của ví dụ của bạn là gì. Tại sao chúng ta tạo bí danh cho 'this'? Và 'xóa obj' sẽ không hoạt động trong không nghiêm ngặt hoặc trừ khi bạn không sử dụng' mới', nhưng điều đó không giống như mục đích dự định của mã. Trừ khi tôi đọc sai, kiểu này có vẻ giống như một câu hỏi của tôi. 1 anyway cho nỗ lực và bởi vì tôi có lẽ chỉ thiếu điểm của bạn;) –

+0

tốt, bí danh này là phong cách của tôi bạn có thể nói. Lý do tôi sử dụng đó là 'this' sẽ không có sẵn dưới các hàm ẩn danh, khi mà một biến' var self' sẽ có sẵn Ồ, về 'delete obj' không hoạt động dưới' new' - tôi không biết (Tôi tương đối mới đối với JS) Ồ, tôi đã đọc sai câu hỏi, đừng bận tâm. – rda3mon

Các vấn đề liên quan