2012-05-23 33 views
8

Về cơ bản tôi cần để có thể làm điều này:Xác định getter trên đối tượng vì vậy tất cả không xác định tra cứu bất động sản trở lại ""

var obj = {"foo":"bar"}, 
    arr = []; 
with(obj){ 
    arr.push(foo); 
    arr.push(notDefinedOnObj); // fails with 'ReferenceError: notDefinedOnObj is not defined' 
} 
console.log(arr); // ["bar", ""] <- this is what it should be. 

Tôi đang tìm kiếm một "" tương đương toàn cầu của {}.__defineGetter__ hoặc {get} để trở lại một chuỗi rỗng cho tất cả các getters thuộc tính không xác định (lưu ý rằng điều này khác với một thuộc tính là undefined).

+0

Bạn có thể sử dụng một [Proxy] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy)? – thisgeek

+0

Nó không giống như 'Proxy' có sẵn trong bất kỳ phiên bản nút nào. :-( –

+0

Vâng, có vẻ như V8 vẫn đang hoạt động trên nó (http://code.google.com/p/v8/issues/detail?id=1543). – thisgeek

Trả lời

7

Bạn có thể tạo một Proxy để trả lại một chuỗi rỗng bất cứ khi nào tính không xác định được truy cập.

app.js:

var obj = {"foo":"bar"}, 
    arr = [], 
    p = Proxy.create({ 
     get: function(proxy, name) { 
      return obj[name] === undefined ? '' : obj[name]; 
     } 
    }); 
arr.push(p.foo); 
arr.push(p.notDefinedOnObj); 

console.log(arr); 

Như câu hỏi tác giả David Murdoch lưu ý, nếu bạn đang sử dụng nút v0.6.18 (phiên bản ổn định mới nhất vào thời điểm bài này được viết), bạn phải vượt qua các tùy chọn --harmony_proxies khi bạn chạy kịch bản:

$ node --harmony_proxies app.js 
[ 'bar', '' ] 

Lưu ý rằng giải pháp này sẽ không công việc nếu bạn sử dụng with, như trong:

var obj = {"foo":"bar"}, 
    arr = [], 
    p = Proxy.create({ 
     get: function(proxy, name) { 
      return obj[name] === undefined ? '' : obj[name]; 
     } 
    }); 
with (p) { 
    arr.push(foo); // ReferenceError: foo is not defined 
    arr.push(notDefinedOnObj); 
} 

console.log(arr); 

with dường như không gọi phương thức get của proxy khi thêm proxy vào chuỗi phạm vi.

Lưu ý: trình xử lý proxy được chuyển đến Proxy.create() trong ví dụ này là không đầy đủ. Xem Proxy: Common mistakes and misunderstanding để biết thêm chi tiết.

+1

Các triển khai proxy khác nhau đều ở mọi nơi. Proxy trong 0.6.x chỉ không hoạt động nếu bạn thực sự muốn truyền proxy xung quanh. Trong 0.7.8 'Object.getPropertyDescriptor' không tồn tại, mặc dù phương thức' getPropertyDescriptor' được yêu cầu trên Proxy và được gọi khi bạn tìm kiếm một thuộc tính không tồn tại (bạn có thể giả mạo nó bằng cách sử dụng 'Object.get * * Riêng ** PropertyDescriptor' thay thế). –

+1

Tôi phát hiện ra rằng [node-proxy] (https://github.com/samshull/node-proxy) (không biên dịch trên Windows ngay bây giờ, lấy 'node-proxy.bin' từ [here] (http://blog.nowjs.com/running-nowjs-natively-on-windows)) Làm việc trên v 0.6.x KHÔNG CÓ bất kỳ cờ dòng lệnh đặc biệt nào. Tuy nhiên, bạn phải trả về 'true' từ phương thức' hasOwn' trên proxy, không phải 'getPropertyDescriptor'. Thật không may, điều này có nghĩa là 'if ((name in obj))' checks sẽ luôn luôn trả về true. –

3

Không có trình xử lý thành viên bị thiếu toàn cầu trong javascript. Bạn sẽ cần phải giới thiệu một chức năng để trừu tượng ra hành vi

function getOrEmpty(obj, name) { 
    if (!obj.hasOwnProperty(name)) { 
    return ""; 
    } 
    return obj[name]; 
} 

var obj = {"foo":"bar"}, 
    arr = []; 
arr.push(getOrEmpty(obj, "foo")); 
arr.push(getOrEmpty(obj, "someUndefinedProperty")); 
console.log(arr); 
+0

Phải, nhưng mã đang chạy là do người dùng tạo ra (từ một khuôn mẫu) .Ngoài ra, hàm 'getOrEmpty' sẽ cần phải gọi' Object.prototype.hasOwnProperty .call (obj, name) 'thay vì kiểm tra giá trị của thuộc tính với giá trị không xác định. Giá trị' undefined' * * có thể được dự định –

+0

ps, ​​tôi đã đề xuất sử dụng 'hasOwnProperty' của nguyên mẫu thay vì' obj' vì nếu 'obj' bằng cách nào đó nhận được thuộc tính' hasOwnProperty', cuộc gọi sẽ Thất bại. Tôi biết trong ví dụ cho điều này không thể xảy ra, nhưng nó là một điều tốt để xem ra cho. –

+0

@DavidMurdoch Tôi đã tìm ra lý do tại sao bạn đề xuất nó. Nhưng nếu mã javascript bắt đầu thay thế các thành viên được xác định trước, bạn về cơ bản là hơi say. Không nói những gì họ đã nổ tung. – JaredPar

0

Với ES6 trở lên, bạn có thể sử dụng Proxy, như câu trả lời được chấp nhận được đề xuất. Nhưng đây là một câu trả lời nếu bạn đang mắc kẹt với ES5.

Với ES5 bạn sẽ phải tạo lớp của riêng bạn, như trong ví dụ này nhanh chóng

function StrictObject() { 
    var values = Object.create(null); 
    this.set = function (key, value) { 
    values[key] = value; 
    }; 
    this.get = function (key) { 
    if (!(key in values)) { 
     throw new Error("Could not find " + key); 
    } 
    return values[key]; 
    }; 
} 
var obj = new StrictObject(); 

obj.set('dad', 'homer'); 
console.log(obj.get('dad')); // homer 
console.log(obj.get('uncle')); // throws error 
Các vấn đề liên quan