2012-04-03 32 views
22

Tôi muốn sử dụng toán tử tồn tại CoffeeScript để kiểm tra một số thuộc tính đối tượng cho không xác định. Tuy nhiên, tôi gặp phải một vấn đề nhỏ.Làm cách nào để sử dụng toán tử tồn tại CoffeeScript để kiểm tra một số thuộc tính đối tượng cho không xác định?

Mã như thế này:

console.log test if test? 

Biên dịch để:

if (typeof test !== "undefined" && test !== null) console.log(test); 

nào là hành vi của tôi muốn thấy. Tuy nhiên, khi tôi cố gắng sử dụng nó chống lại các thuộc tính đối tượng, như thế này:

console.log test.test if test.test? 

tôi nhận được một cái gì đó như thế:

if (test.test != null) console.log(test.test); 

nào desn't trông giống như một tấm séc chống lại không xác định gì cả. Cách duy nhất tôi có thể đạt được cùng một hành vi (1: 1) như sử dụng nó cho các đối tượng là bằng cách sử dụng một kiểm tra lớn hơn:

console.log test.test if typeof test.test != "undefined" and test.test != null 

Câu hỏi đặt ra là - tôi có làm điều gì sai? Hoặc là mã được biên dịch là đủ để kiểm tra sự tồn tại của một thuộc tính (một kiểm tra rỗng với kiểu chuyển đổi)?

+0

bản sao chính xác của [coffeescript không phải là hành vi rỗng hoặc không xác định] (http://stackoverflow.com/questions/20010245/coffeescript-not-null-or-undefined-behavior) – Bergi

+0

@Bergi, câu hỏi này được hỏi bốn năm trước , cái kia - hai năm trước. Không phải là một bản sao khác? :) – Przemek

+1

Phải, tôi chỉ cảm thấy người kia có câu trả lời tốt hơn. Tôi đoán họ nên được sáp nhập. – Bergi

Trả lời

44

Đây là một điểm chung của sự nhầm lẫn với các nhà điều hành hiện sinh: Đôi khi

x? 

biên dịch để

typeof test !== "undefined" && test !== null 

và những lúc khác nó chỉ biên dịch thành

x != null 

Hai là tương đương,x != null sẽ false khi x là một trong hai null hoặc undefined. Vì vậy, x != null là một cách nhỏ gọn hơn để biểu thị (x !== undefined && x !== null). Lý do trình biên dịch typeof xảy ra là trình biên dịch nghĩ rằng x có thể chưa được xác định, trong trường hợp đó, việc kiểm tra bình đẳng sẽ kích hoạt ReferenceError: x is not defined.

Trong trường hợp cụ thể, test.test có thể có giá trị undefined, nhưng bạn không thể có được ReferenceError bằng cách tham chiếu đến thuộc tính chưa xác định trên đối tượng hiện có, do đó trình biên dịch sẽ chọn đầu ra ngắn hơn.

+0

Cảm ơn! Ngắn gọn và cung cấp thông tin cho những người đã tránh Javascript trước Coffeescript :) – Seth

4

phỏng đoán hoang dã; bạn đã thử console.log test.test if test?.test? chưa?

Chỉ cần thử nghiệm nó với coffee -p -e 'console.log test.test if test?.test?', mà biên dịch để:

(function() {

if ((typeof test !== "undefined" && test !== null ? test.test : void 0) != null) { console.log(test.test); }

}).call(this);

+0

Điều này thực sự hữu ích và chính xác lý do tôi kết thúc câu hỏi này, vì vậy hãy bỏ phiếu cho điều đó! Làm cho các câu lệnh if ngắn gọn hơn rất nhiều. – peteski

20

JavaScript này:

a.foo != null 

thực sự không kiểm tra xem foo tài sản của a không phải là undefined cũng không null.Lưu ý rằng a.foo? được dịch sang JavaScript sử dụng != null thay vì !== null. Quá trình chuyển đổi đó != không có nghĩa rằng cả hai là đúng:

null == null 
undefined == null 

Một đồng bằng a? trở JavaScript này:

typeof a !== "undefined" && a !== null 

vì có ba điều kiện để kiểm tra:

  1. Có một số a ở phạm vi nào?
  2. a có giá trị là undefined không?
  3. a có giá trị là null không?

Điều kiện đầu tiên là quan trọng như chỉ nói a != null sẽ kích hoạt một ReferenceError nếu không có a trong phạm vi nhưng nói typeof a === 'undefined' sẽ không. Kiểm tra typeof cũng đảm bảo điều kiện a === undefined trong . Sau đó, chúng ta có thể kết thúc nó đi với một a !== null kiểm tra nghiêm ngặt như rằng sẽ chăm sóc của mà không có hình phạt hiệu suất của một không cần thiết != (lưu ý: !=== là chậm hơn so với !===== do sự chuyển đổi ngầm).

Một đọc chút về những gì !=!== làm có thể là hiệu quả:

MDN: Comparison Operators


Theo như nhận xét của bạn về câu trả lời đã xóa là có liên quan, if(a.foo) là hoàn toàn hợp lệ cú pháp nếu bạn hoàn thành if tuyên bố:

if(a.foo) 
    do_interesting_things() 
# or 
do_interesting_things() if(a.foo) 

Tuy nhiên, if(a.foo)if(a.foo?) khác nhau về cách chúng xử lý 0, false''.

+0

kết quả đầu tiên trên google; nhưng thực sự! == trả về lỗi. chúng ta có thể làm rõ? – Ben

+0

@Ben: Không chắc chắn ý bạn là gì, việc sử dụng '! ==' trả về lỗi và lỗi là gì? –

+0

coffeecript-rails (coffeescript 2.2.0), "SyntaxError: [stdin]: 37: 38: unexpected ="; một lỗi 500 tốt đẹp, nó chỉ không biên dịch với một nhân vật thứ ba trong các yếu tố so sánh – Ben

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