2012-01-09 20 views
72

Mỗi khi có ai đề cập đến thử nghiệm đối với undefined, it's pointed out thì undefined không phải là từ khóa để it could be set to "hello", vì vậy, you should usetypeof x == "undefined" thay thế. Điều này có vẻ vô lý đối với tôi. Không ai có thể làm điều đó, và nếu họ đã làm nó sẽ là lý do đủ để không bao giờ sử dụng bất kỳ mã họ đã viết ... phải không?Làm thế nào nguy hiểm trong JavaScript, thực sự, giả định không xác định không bị ghi đè?

tôi thấy one example của một ai đó vô tình thiết lập undefined để null, và điều này đã được đưa ra như một lý do để tránh giả định rằng undefined không bị ghi đè. Nhưng nếu họ làm thế, con bọ sẽ không bị phát hiện, và tôi không thấy nó tốt hơn thế nào.

Trong C++, mọi người đều ý thức được rằng nói pháp lý là #define true false, nhưng không ai khuyên bạn tránh sử dụng true và sử dụng 0 == 0 thay thế. Bạn chỉ cần giả định rằng không ai có thể là một người giật đủ lớn để làm điều đó, và nếu họ làm, không bao giờ tin tưởng mã của họ một lần nữa.

Đã bao giờ thực sự cắn ai đó mà người khác được giao cho undefined (có mục đích) và nó đã phá vỡ mã của bạn, hay đây là một mối đe dọa giả định hơn? Tôi sẵn sàng tận dụng cơ hội để làm cho mã của tôi dễ đọc hơn. Đây có phải là một ý tưởng thực sự tồi không?

Để nhắc lại, tôi là không phải yêu cầu cách bảo vệ chống lại việc gán lại chưa được xác định. Tôi đã nhìn thấy những thủ thuật được viết 100 lần rồi. Tôi hỏi làm thế nào nguy hiểm là không sử dụng những thủ thuật.

+6

Tôi sẽ rất vui, nhưng tôi không cảm thấy như bất kỳ câu trả lời nào trong ba câu trả lời đều là một công việc tốt trong việc trả lời câu hỏi. Tôi đã cố gắng để làm cho nó rõ ràng tôi đã không yêu cầu cho một rehash của câu trả lời tôi liên kết với, nhưng đó vẫn là những gì tôi có. Nếu nó được coi là gauche không chấp nhận một câu trả lời ngay cả khi nó không phải là những gì tôi đã yêu cầu, cho tôi biết và tôi sẽ đi trước và chấp nhận một! – Cosmologicon

+1

Tôi nghĩ rằng tất cả các sự kiện được đặt ra ở đây, mặc dù. Vì vậy, những gì bạn đang nói là bạn muốn có một câu trả lời chủ quan hoặc ý kiến ​​thay vào đó, mà chỉ dẫn đến sự bất đồng. Đó là lý do cụm từ "thực hành tốt nhất" không được phép trong tiêu đề câu hỏi. Bạn là người duy nhất có thể biết mức độ nguy hiểm trong kịch bản của bạn.Và nếu bạn đang viết một thư viện phổ biến mà bạn không kiểm soát tất cả các 'biến', hàm wrapper (undefined) {} ​​có vẻ là một câu trả lời xuất sắc. Tại sao không sử dụng nó và chấp nhận câu trả lời đó? – shannon

+3

Nếu ai đó lo lắng về việc ai đó định nghĩa lại 'undefined', bạn nên lo lắng nhiều hơn về việc ai đó định nghĩa lại 'XMLHttpRequest' hoặc' alert'. Tất cả các hàm chúng ta sử dụng từ 'window' có thể đã được định nghĩa lại. Và nếu bạn chỉ lo lắng về một đồng nghiệp làm điều đó một cách tình cờ, tại sao tin tưởng họ không làm 'window.addEventListener =" coolbeans "'? Câu trả lời là không phải lo lắng về bất kỳ điều đó. Nếu ai đó đang tiêm chích JS một cách độc hại vào trang của bạn thì bạn vẫn bị hosed. Làm việc để ngăn chặn * rằng * xảy ra ở nơi đầu tiên. –

Trả lời

45

Không, tôi chưa bao giờ có. Điều này chủ yếu là do tôi phát triển trên các trình duyệt hiện đại, phần lớn tuân thủ ECMAScript 5. Tiêu chuẩn ES5 quy định rằng undefined giờ đây chỉ đọc. Nếu bạn sử dụng chế độ nghiêm ngặt (bạn nên), một lỗi sẽ bị ném nếu bạn vô tình cố sửa đổi nó.

undefined = 5; 
alert(undefined); // still undefined 
'use strict'; 
undefined = 5; // throws TypeError 

Những gì bạn nên không làm là tạo riêng của bạn scoped, có thể thay đổi undefined:

(function (undefined) { 
    // don't do this, because now `undefined` can be changed 
    undefined = 5; 
})(); 

liên tục là tốt. Vẫn không cần thiết, nhưng tốt.

(function() { 
    const undefined = void 0; 
})(); 
+0

Tuyên bố đầu tiên của bạn chỉ đảm bảo bạn không vô tình ghi đè lên không xác định trong khi phát triển, nó vẫn đặt ra cùng một mối đe dọa khi chạy với mã khác trên máy tính khách. – bennedich

+1

@bennedich: Tôi biết, tôi đã nói rằng tôi chưa bao giờ gặp phải vấn đề đó, nhưng * đây là những gì bạn nên làm *. – Ryan

+3

+1 bởi vì bạn là người duy nhất thực sự trả lời một phần câu hỏi ... – Izkata

41

Không có mã thích hợp nào sẽ thực hiện việc như vậy. Nhưng bạn không bao giờ có thể biết những gì một số nhà phát triển wannabe thông minh hoặc một plugin/thư viện/script bạn đang sử dụng đã làm. Mặt khác, các trình duyệt hiện đại và không chắc chắn sẽ không cho phép ghi đè lên undefined, vì vậy nếu bạn đang sử dụng trình duyệt như vậy để phát triển, bạn sẽ nhanh chóng nhận thấy nếu có bất kỳ mã nào cố gắng ghi đè lên nó.


Và mặc dù bạn không yêu cầu nó - nhiều người có thể sẽ tìm thấy câu hỏi này khi tìm kiếm phổ biến hơn "làm thế nào để bảo vệ chống lại định nghĩa lại undefined" vấn đề, vì vậy tôi sẽ trả lời rằng anyway:

có một cách rất tốt để có được một sự không xác địnhundefined dù bao nhiêu tuổi trình duyệt là:

(function(undefined) { 
    // your code where undefined is undefined 
})(); 

này hoạt động vì một cuộc tranh cãi mà không được chỉ định luôn là 012..Bạn cũng có thể làm điều đó với một hàm chấp nhận một số đối số thực, ví dụ: như thế này khi bạn đang sử dụng jQuery. Nó thường là một ý tưởng tốt để đảm bảo một môi trường lành mạnh theo cách này:

(function($, window, undefined) { 
    // your code where undefined is undefined 
})(jQuery, this); 

Sau đó, bạn có thể chắc chắn rằng bên trong đó chức năng ẩn danh những điều sau đây là đúng:

  • $ === jQuery
  • window === [the global object]
  • undefined === [undefined].

Tuy nhiên, lưu ý rằng đôi khi typeof x === 'undefined' là thực sự cần thiết: Nếu biến x chưa bao giờ được thiết lập để một giá trị (trái với việc thiết-undefined), đọc x theo một cách khác nhau như if(x === undefined) sẽ ném một lỗi. Tuy nhiên, điều này không áp dụng cho các thuộc tính đối tượng, vì vậy nếu bạn biết rằng y luôn là một đối tượng, thì if(y.x === undefined) là hoàn toàn an toàn.

+2

Câu lệnh của bạn về 'x' không được đặt thành giá trị không hoàn toàn đúng (xem http://jsfiddle.net/MgADz/); nó đúng hơn nếu nó thực sự thực sự * không được định nghĩa * (xem http://jsfiddle.net/MgADz/1/). – Ryan

+0

Xem câu trả lời của tôi về việc nhận giá trị không xác định thực là hằng số không thể thay đổi do nhầm lẫn (tham số 'undefined' của bạn có thể thay đổi nếu' = 'được gõ thay vì' == 'hoặc' === 'khi so sánh với undefined – Lucero

+0

@Lucero: Có bao nhiêu người bạn thấy vô tình gõ 'undefined = someVariable'? Bạn thường đi theo cách khác ... 'someVariable === undefined'. – Ryan

19

Có một giải pháp đơn giản cho điều đó: so sánh với void 0 luôn không xác định.

Lưu ý rằng bạn nên tránh == vì nó có thể ép buộc các giá trị. Sử dụng === (và !==) để thay thế.

Điều đó nói rằng, biến không xác định có thể được đặt bằng lỗi nếu ai đó viết = thay vì == khi so sánh một số nội dung với undefined.

+0

IMO, đây là câu trả lời hay nhất. – abhisekp

+1

Hãy xem xét rằng 'foo === void 0' có thể không đọc trơn tru như' foo === undefined' và 'không xác định' bất biến được hỗ trợ đầy đủ bởi các trình duyệt hiện đại (IE 9+) như bạn có thể thấy trong [this] (http://kangax.github.io/compat-table/es5/#test-Immutable_undefined) bảng tương thích. –

3

Chỉ bạn biết mã nào bạn sử dụng và do đó mức độ nguy hiểm. Câu hỏi này không thể được trả lời theo cách bạn đã làm rõ bạn muốn nó trả lời.

1) Tạo chính sách nhóm, không cho phép xác định lại không xác định, đặt trước để sử dụng phổ biến hơn. Quét mã hiện tại của bạn để chỉ định trái không xác định.

2) Nếu bạn không kiểm soát tất cả các tình huống, nếu mã của bạn được sử dụng bên ngoài các tình huống bạn hoặc chính sách của bạn kiểm soát, thì rõ ràng câu trả lời của bạn là khác nhau. Quét mã sử dụng tập lệnh của bạn. Heck, quét web để biết số liệu thống kê của việc phân công trái không xác định nếu bạn muốn, nhưng tôi nghi ngờ điều đó đã được thực hiện cho bạn, bởi vì dễ dàng hơn khi chỉ theo đuổi câu trả lời # 1 hoặC# 3 ở đây thay thế.

3) Và nếu câu trả lời đó không đủ tốt, có thể bởi vì, một lần nữa, bạn cần một câu trả lời khác. Có thể bạn đang viết một thư viện phổ biến sẽ được sử dụng bên trong tường lửa của công ty và bạn không có quyền truy cập vào mã gọi điện. Sau đó sử dụng một trong những câu trả lời tốt khác ở đây. Lưu ý tập tin thư viện jQuery đóng gói âm thanh phổ biến và bắt đầu:

(function(window, undefined) { 

Chỉ bạn mới có thể trả lời câu hỏi theo cách cụ thể mà bạn tìm kiếm. Còn gì nữa để nói?

chỉnh sửa: p.s. nếu bạn thực sự muốn ý kiến ​​của tôi, tôi sẽ nói với bạn rằng nó không nguy hiểm chút nào. Bất cứ điều gì có thể gây ra lỗi (chẳng hạn như gán cho không xác định, đó rõ ràng là một hành vi nguy hiểm được ghi chép đầy đủ) là một lỗi. Đó là lỗi đó là rủi ro. Nhưng đó chỉ là trong kịch bản của tôi, nơi tôi có thể đủ khả năng để giữ quan điểm đó. Như tôi đã đề nghị bạn làm, tôi đã trả lời câu hỏi cho các trường hợp sử dụng của tôi.

3

Thật an toàn để kiểm tra không được xác định. Như bạn đã đề cập. Nếu bạn nhận được một số mã ghi đè lên nó (điều này rất có thể xảy ra), bạn không nên sử dụng nó nữa.

Có thể nếu bạn đang tạo thư viện để sử dụng công khai, bạn có thể sử dụng một số kỹ thuật để tránh người dùng thay đổi nó. Nhưng ngay cả trong trường hợp này, đó là vấn đề của họ, không phải thư viện của bạn.

0

Nó không nguy hiểm chút nào. Nó chỉ có thể được ghi đè khi chạy trên một động cơ ES3 và nó không có khả năng được sử dụng nữa.

0

Trước hết, nếu mã của bạn bị hỏng, có thể không phải vì một số nhà phát triển khác ở đó "đang cố gắng trở thành một kẻ giật gân" khi bạn đặt nó.

Đúng là undefined không phải là từ khóa. Nhưng nó nguyên thủy cấp toàn cầu. Nó được dự định sẽ được sử dụng như thế này (xem "không xác định" tại developer.mozilla.org):

var x; 
if (x === undefined) { 
    // these statements execute 
} 
else { 
    // these statements do not execute 
} 

Việc thay thế chung cho rằng (cũng từ MDN) và theo ý kiến ​​của tôi một cách tốt hơn là:

// x has not been declared before 
if (typeof x === 'undefined') { // evaluates to true without errors 
    // these statements execute 
} 

if(x === undefined){ // throws a ReferenceError 

} 

Trong đó có một vài lợi thế, một trong những lợi thế rõ ràng (từ các ý kiến) là nó không kích hoạt một ngoại lệ khi x không được khai báo. Nó cũng đáng chú ý là MDN cũng chỉ ra rằng điều quan trọng là sử dụng === qua == trong trường hợp đầu tiên vì:

var x=null; 
if (x === undefined) { 
    // this is probably what you meant to do 
    // these lines will not execute in this case 
} 
else if (x == undefined) { 
    // these statements will execute even though x *is* defined (as null) 
} 
else { 
    // these statements do not execute 
} 

Đây là một lý do thường bị bỏ qua lý do tại sao nó có lẽ là tốt hơn để chỉ cần sử dụng thay thế thứ hai trong tất cả các trường hợp.

Kết luận: Không sai khi viết mã theo cách đầu tiên và chắc chắn không nguy hiểm. Các đối số bạn đã thấy rằng bạn sử dụng như một ví dụ chống lại nó (rằng nó có thể được ghi đè) không phải là đối số mạnh nhất để mã hóa các thay thế với typeof. Nhưng sử dụng typeof mạnh hơn vì một lý do cụ thể: nó không ném một ngoại lệ khi var của bạn không được khai báo. Cũng có thể lập luận rằng việc sử dụng == thay vì === là một sai lầm phổ biến trong trường hợp đó nó không làm những gì bạn mong đợi. Vậy tại sao không sử dụng typeof?

+1

"Trong đó có một vài lợi thế, rõ ràng là nó không kích hoạt một ngoại lệ khi x không được khai báo." Hãy để tôi thực hiện việc này ngay lập tức. Bạn nghĩ rằng đó là một * lợi thế * để âm thầm bỏ qua ngoại lệ xảy ra khi bạn sử dụng một biến không khai báo? Điều đó có vẻ rất dễ bị lỗi. Bạn có thể giải thích tại sao bạn nghĩ đó không phải là một bất lợi khủng khiếp? – Cosmologicon

1

Bạn có thể sử dụng undefined trong mã của mình khi mã hóa cho trình duyệt hỗ trợ ECMAScript 5.1 vì nó là immutable according to the language specification.

Xem thêm this bảng tính tương thích hoặc thiscaniuse ECMAScript 5 để thấy rằng tất cả các trình duyệt hiện đại (IE 9+) đã thực hiện bất biến undefined.

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