2011-12-16 45 views
20

Dường như với tôi rằng có bốn cách khác nhau tôi có thể xác định liệu một đối tượng nhất định (ví dụ foo) có một tài sản nhất định (ví dụ bar) định nghĩa:JavaScript: Là thành viên được xác định?

  1. if (foo.hasOwnProperty(bar)) {
  2. if ('bar' in foo) {
  3. if (typeof foo.bar !== 'undefined') {
  4. if (foo.bar === undefined) {

Để xác định xem có thích hợp không ty có tên "bar" trong đối tượng foo, tất cả đều là ba trong số những tuyên bố tương đương? Có bất kỳ ngữ nghĩa sublte tôi không biết rằng làm cho bất kỳ của ba báo cáo khác nhau?

+1

Cần lưu ý rằng, trừ khi ai đó ghi đè biến 'undefined' toàn cầu, 3 cũng có thể được thực hiện như' if (foo.bar! == không xác định) {'. – Domenic

Trả lời

17

Không có gì khác biệt hoàn toàn. Ví dụ:

foo = {bar: undefined}; 
Object.prototype.baz = undefined; 
Object.prototype.bing = "hello"; 

Sau đó:

(typeof foo.bar != "undefined") === false 
('bar' in foo)     === true 
(foo.hasOwnProperty('bar'))  === true 


(typeof foo.baz != "undefined") === false 
('baz' in foo)     === true 
(foo.hasOwnProperty('baz'))  === false 


(typeof foo.bing != "undefined") === true 
('bing' in foo)     === true 
(foo.hasOwnProperty('bing'))  === false 

Logic-khôn ngoan:

  • foo.hasOwnProperty('bar') ngụ ý 'bar' in foo
  • typeof foo.bar != "undefined" ngụ ý 'bar' in foo
  • Nhưng đó là những suy luận duy nhất mà bạn có thể rút ra; không có tác động nào khác là phổ quát, như các mẫu đối chứng trên cho thấy.
+1

+1 - Tôi quên xem thanh đang ở trên foo nhưng được đặt thành không xác định –

2

một khác biệt là, phương pháp 1 sẽ chỉ kiểm tra đối tượng foo cho thanh thuộc tính trong khi hai phương thức cuối cùng cũng sẽ kiểm tra nguyên mẫu cho thuộc tính kế thừa.

2
'bar' in foo 

sẽ tìm bất kỳ đâu trong chuỗi nguyên mẫu. Kiểm tra để xem nếu foo.bar! == undefined cũng sẽ trở thành sự thật nếu bar là bất cứ nơi nào trong foo 's chuỗi nguyên mẫu, nhưng hãy nhớ nếu thanh được xác định trên foo, và thiết lập để không xác định, điều này sẽ trả về false.

hasOwnProperty là lựa chọn nhiều hơn - nó sẽ chỉ trả lại đúng là bar được định nghĩa là tài sản trực tiếp của foo.

mỗi MDN

Mỗi đối tượng có nguồn gốc từ Object kế thừa phương pháp hasOwnProperty. Phương pháp này có thể được sử dụng để xác định xem một đối tượng có thuộc tính được chỉ định là là thuộc tính trực tiếp của đối tượng đó hay không; không giống như toán tử , phương pháp này không kiểm tra chuỗi nguyên mẫu của đối tượng.

10

Đây là tất cả khác nhau:

  1. foo.hasOwnProperty('bar') cho bạn biết liệu foo có tài sản và không thực hiện tra cứu dọc theo chuỗi nguyên mẫu.

  2. 'bar' in foo kiểm tra chuỗi nguyên mẫu và trả về true khi tìm thấy thuộc tính bar trong bất kỳ đối tượng nào dọc theo chuỗi.

  3. typeof foo.bar != 'undefined' trả về true nếu foo hoặc bất kỳ đối tượng cùng chuỗi nguyên mẫu của nó có hữu bar và giá trị của nó không phải là undefined.

Dưới đây là một ví dụ chứng minh rằng những khác biệt này:

var foo1 = { 'bar1': 10, 'bar2': undefined }; 
function ctor() {} 
ctor.prototype = foo1; 
var foo2 = new ctor(); 
foo2.bar3 = 20; 

console.log(foo2.hasOwnProperty('bar1')); // false 
console.log(foo2.hasOwnProperty('bar2')); // false 
console.log(foo2.hasOwnProperty('bar3')); // true 
console.log(foo2.hasOwnProperty('bar4')); // false 

console.log('bar1' in foo2); // true 
console.log('bar2' in foo2); // true 
console.log('bar3' in foo2); // true 
console.log('bar4' in foo2); // false 

console.log(typeof foo2.bar1 != 'undefined'); // true 
console.log(typeof foo2.bar2 != 'undefined'); // false 
console.log(typeof foo2.bar3 != 'undefined'); // true 
console.log(typeof foo2.bar4 != 'undefined'); // false 
2

Có thực sự một số khác biệt tinh tế giữa các phương pháp khác nhau/từ khóa.

  1. foo.hasOwnProperty('bar') trả về true nếu thanh 'tài sản' được xác định trên chính đối tượng foo. Các thuộc tính khác, chẳng hạn như 'toString' sẽ trả về false tuy nhiên vì chúng được định nghĩa trong chuỗi nguyên mẫu.

  2. Toán tử từ khóa in trả về true nếu thuộc tính được chỉ định nằm trong đối tượng được chỉ định. Cả hai 'bar' in foo'toString' in foo sẽ trả về true.

  3. Vì bạn đang kiểm tra trạng thái của thuộc tính, kết quả sẽ đúng khi thanh không được xác định trên foo và khi thanh được xác định nhưng giá trị được đặt thành undefined.

0

Để thêm vào những gì người khác đã nói, nếu bạn chỉ muốn biết nếu một tài sản tồn tại và có một giá trị không falsey (không undefined, null, false, 0, "", NaN, vv ...), bạn chỉ có thể làm điều này:

if (foo.bar) { 
    // code here 
} 

chừng nào giá trị falsey không thú vị cho bạn cho hoàn cảnh cụ thể của bạn, phím tắt này sẽ cho bạn biết nếu biến đã được thiết lập để một cái gì đó hữu ích cho bạn hay không.

Nếu bạn muốn biết nếu tài sản tồn tại trên các đối tượng trong bất kỳ cách nào, tôi tìm thấy điều này hữu ích nhất, ngắn gọn và dễ đọc:

if ('bar' in foo) { 
    // code here 
} 

Người ta cũng có thể sử dụng một cái gì đó tương tự như trên đối số chức năng (một lần nữa như miễn là giá trị falsey không phải là điều bạn quan tâm):

function foo(bar) { 
    if (bar) { 
     // bar was passed and has some non-falsey value 
    } 
} 
Các vấn đề liên quan