2010-01-07 44 views
59

Các đối tượng/biến JavaScript có một số loại số nhận dạng duy nhất không? Giống như Ruby có object_id. Tôi không có nghĩa là thuộc tính id DOM, mà là một số loại địa chỉ bộ nhớ của một số loại.Id đối tượng JavaScript

+2

Bạn đang tìm cách so sánh các đối tượng bằng cách sử dụng object_id? – Upperstage

+0

Xem http://stackoverflow.com/questions/1997661/unique-object-identifier-in-javascript –

Trả lời

36

Không, các đối tượng không có một xây dựng trong nhận dạng, mặc dù bạn có thể thêm một bằng cách thay đổi mẫu đối tượng. Dưới đây là ví dụ về cách bạn có thể làm điều đó:

(function() { 
    var id = 0; 

    function generateId() { return id++; }; 

    Object.prototype.id = function() { 
     var newId = generateId(); 

     this.id = function() { return newId; }; 

     return newId; 
    }; 
})(); 

Điều đó nói rằng, nói chung sửa đổi nguyên mẫu đối tượng được coi là thực hành rất xấu. Thay vào đó, tôi khuyên bạn nên gán id theo cách thủ công cho các đối tượng khi cần hoặc sử dụng hàm touch như những người khác đã đề xuất.

+0

ActionScript 3 có đối tượng Dictionary sử dụng sự bình đẳng nghiêm ngặt để so sánh khóa, vì vậy người ta có thể sử dụng các đối tượng làm khóa. Có một tương đương trong JavaScript, hoặc bạn sẽ phải tự xây dựng id duy nhất cho mọi đối tượng (hoặc thông qua Object.prototype hoặc tự thêm một id để chọn đối tượng)? – Triynko

+0

Thật không may javascript không có bất cứ điều gì như thế. Âm thanh như bạn sẽ phải cung cấp cho các đối tượng id và sau đó sử dụng những id như là chìa khóa trong đối tượng, như bạn đề nghị. Điều đó nói rằng, nếu bạn thực sự muốn được thông minh, bạn có thể thực hiện "đối tượng id" bằng cách ghi đè phương thức 'toString' và sử dụng chúng như thế này 'id = new Id(); bộ nhớ cache [id] = obj'. Đó là một chút hạt nhưng khá thú vị. Đây là một bài viết tôi đã viết giải thích kỹ thuật này chi tiết hơn: http://xavi.co/articles/fun-with-tostring-in-javascript – Xavi

+0

Được rồi, tôi vừa phát hiện ra lý do. jQuery cũng ghi đè ID và bằng cách nào đó trang của tôi đã bị phá vỡ khi tôi override nó. Hah. Đuợc. Vì thế. Tôi sẽ chỉ tránh các vấn đề đặt tên và vượt qua các ngón tay của tôi. – Lodewijk

8

Trên thực tế, bạn không cần phải sửa đổi các nguyên mẫu object. Sau đây nên làm việc để 'có được' id duy nhất cho bất kỳ đối tượng, đủ hiệu quả.

var __next_objid=1; 
function objectId(obj) { 
    if (obj==null) return null; 
    if (obj.__obj_id==null) obj.__obj_id=__next_objid++; 
    return obj.__obj_id; 
} 
+6

Chỉ cần lưu ý rằng điều này sẽ không chơi độc đáo với hầu hết các cách sao chép các đối tượng, nếu bạn mong đợi các đối tượng có id khác nhau sau đó. –

+0

Thật vậy, bạn cần có một hàm "copyObject" đặc biệt để tính riêng __obj_id này. Bạn cũng phải chắc chắn rằng không có xung đột với việc sử dụng "__obj_id" trong các thư viện khác. Điều này dễ dàng hơn nhiều trong ActionScript, mà đối tượng Dictionary sử dụng so sánh bình đẳng nghiêm ngặt trên các khóa, bao gồm các đối tượng được sử dụng làm khóa. Trong thực tế, bạn có thể có thể viết một lớp từ điển trong JS tự động gắn các id theo cách này cho các đối tượng được thêm vào nó như là các khóa. Nó giống như ID JavaScript cơ học lượng tử; chúng không tồn tại cho đến khi bạn cố gắng quan sát chúng với hàm này, haha. – Triynko

1

Tôi vừa xem qua điều này và nghĩ tôi sẽ thêm suy nghĩ của mình. Như những người khác đã gợi ý, tôi khuyên bạn nên ID bằng tay thêm, nhưng nếu bạn thực sự muốn một cái gì đó gần với những gì bạn đã mô tả, bạn có thể sử dụng này:

var objectId = (function() { 
    var allObjects = []; 

    var f = function(obj) { 
     if (allObjects.indexOf(obj) === -1) { 
      allObjects.push(obj); 
     } 
     return allObjects.indexOf(obj); 
    } 
    f.clear = function() { 
     allObjects = []; 
    }; 
    return f; 
})(); 

Bạn có thể lấy ID của bất kỳ đối tượng bằng cách gọi objectId(obj). Sau đó, nếu bạn muốn id là thuộc tính của đối tượng, bạn có thể mở rộng mẫu thử nghiệm:

Object.prototype.id = function() { 
    return objectId(this); 
} 

hoặc bạn có thể thêm ID theo cách thủ công cho từng đối tượng bằng cách thêm chức năng tương tự làm phương pháp. Điều quan trọng nhất là điều này sẽ ngăn chặn bộ thu gom rác phá hủy các đối tượng khi chúng rơi ra khỏi phạm vi ... chúng sẽ không bao giờ rơi ra khỏi phạm vi của mảng allObjects, vì vậy bạn có thể thấy rò rỉ bộ nhớ là một vấn đề. Nếu thiết lập của bạn sử dụng phương pháp này, bạn nên làm như vậy cho mục đích gỡ lỗi. Khi cần, bạn có thể làm objectId.clear() để xóa allObjects và để cho GC thực hiện công việc của mình (nhưng từ thời điểm đó, các id đối tượng sẽ được đặt lại).

+0

Tôi nghĩ rằng đây là một giải pháp chậm nhưng mạnh mẽ và có thể được cải thiện một chút: '' ' var objectId = (function() { var mem = []; var f = function (obj) { var r = mem.indexOf (obj); if (r === -1) { r = mem.length; mem.push (obj); } trở r; }; f.reset = function() { return mem = []; }; return f; })(); '' ' – luochen1990

+0

@ luochen1990, tôi nghĩ bạn sẽ ngạc nhiên với tốc độ của nó. (Nhưng bạn nói đúng, cách tốt hơn là đặt kết quả indexOf() vào một biến, mặc dù tôi sẽ tranh luận nó từ quan điểm DRY chứ không phải tối ưu hóa.) Miễn là vấn đề GC có thể được quản lý hiệu quả, tôi nghĩ bạn ' d phải có nhiều helluva đối tượng để nhận thấy bất kỳ tác động hiệu suất đáng kể nào. –

21

Nếu bạn muốn tra cứu/kết hợp một đối tượng với một định danh duy nhất mà không sửa đổi các đối tượng cơ bản, bạn có thể sử dụng một WeakMap:

// Note that object must be an object or array, 
// NOT a primitive value like string, number, etc. 
var objIdMap=new WeakMap, objectCount = 0; 
function objectId(object){ 
    if (!objIdMap.has(object)) objIdMap.set(object,++objectCount); 
    return objIdMap.get(object); 
} 

var o1={}, o2={}, o3={a:1}, o4={a:1}; 
console.log(objectId(o1)) // 1 
console.log(objectId(o2)) // 2 
console.log(objectId(o1)) // 1 
console.log(objectId(o3)) // 3 
console.log(objectId(o4)) // 4 
console.log(objectId(o3)) // 3 

Sử dụng một WeakMap đảm bảo rằng các đối tượng vẫn có thể được thu gom rác.

+0

Câu trả lời hay nhất! Sử dụng bộ nhớ O (n) trong đó n là số đối tượng có ID mà bạn quan tâm (chứ không phải là n = tất cả các đối tượng) và không ảnh hưởng đến việc thu thập rác. –

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