問題描述
- 是否可以確定一個 javascript 對象是否有多個引用?
- 或者如果它有引用除了我正在訪問它的那個?
- 或者甚至只是為了獲取引用計數本身?
- 我能否從 javascript 本身中找到這些信息,或者我是否需要跟蹤我自己的引用計數器.
顯然,我的代碼必須至少有一個對它的引用才能訪問該對象.但我想知道是否有其他引用它,或者我的代碼是否是唯一可以訪問它的地方.如果沒有其他對象引用它,我希望能夠刪除該對象.
Obviously, there must be at least one reference to it for my code access the object. But what I want to know is if there are any other references to it, or if my code is the only place it is accessed. I'd like to be able to delete the object if nothing else is referencing it.
如果您知道答案,則無需閱讀此問題的其余部分.以下只是一個示例,以使事情更清楚.
If you know the answer, there is no need to read the rest of this question. Below is just an example to make things more clear.
在我的應用程序中,我有一個名為 contacts
的 Repository
對象實例,其中包含 ALL 我的聯系人數組.還有多個 Collection
對象實例,例如 friends
集合和 coworkers
集合.每個集合都包含一個數組,其中包含來自 contacts
Repository
的一組不同項.
In my application, I have a Repository
object instance called contacts
that contains an array of ALL my contacts. There are also multiple Collection
object instances, such as friends
collection and a coworkers
collection. Each collection contains an array with a different set of items from the contacts
Repository
.
為了使這個概念更具體,請考慮下面的代碼.Repository
對象的每個實例都包含一個特定類型的所有項目的列表.您可能有一個聯系人存儲庫和一個單獨的事件存儲庫.為簡單起見,您可以獲取、添加和刪除項目,并通過構造函數添加許多項目.
To make this concept more concrete, consider the code below. Each instance of the Repository
object contains a list of all items of a particular type. You might have a repository of Contacts and a separate repository of Events. To keep it simple, you can just get, add, and remove items, and add many via the constructor.
var Repository = function(items) {
this.items = items || [];
}
Repository.prototype.get = function(id) {
for (var i=0,len=this.items.length; i<len; i++) {
if (items[i].id === id) {
return this.items[i];
}
}
}
Repository.prototype.add = function(item) {
if (toString.call(item) === "[object Array]") {
this.items.concat(item);
}
else {
this.items.push(item);
}
}
Repository.prototype.remove = function(id) {
for (var i=0,len=this.items.length; i<len; i++) {
if (items[i].id === id) {
this.removeIndex(i);
}
}
}
Repository.prototype.removeIndex = function(index) {
if (items[index]) {
if (/* items[i] has more than 1 reference to it */) {
// Only remove item from repository if nothing else references it
this.items.splice(index,1);
return;
}
}
}
注意 remove
中帶有注釋的行.如果沒有其他對象引用該項目,我只想從我的對象主存儲庫中刪除該項目.這是集合
:
Note the line in remove
with the comment. I only want to remove the item from my master repository of objects if no other objects have a reference to the item. Here's Collection
:
var Collection = function(repo,items) {
this.repo = repo;
this.items = items || [];
}
Collection.prototype.remove = function(id) {
for (var i=0,len=this.items.length; i<len; i++) {
if (items[i].id === id) {
// Remove object from this collection
this.items.splice(i,1);
// Tell repo to remove it (only if no other references to it)
repo.removeIndxe(i);
return;
}
}
}
然后這段代碼使用Repository
和Collection
:
var contactRepo = new Repository([
{id: 1, name: "Joe"},
{id: 2, name: "Jane"},
{id: 3, name: "Tom"},
{id: 4, name: "Jack"},
{id: 5, name: "Sue"}
]);
var friends = new Collection(
contactRepo,
[
contactRepo.get(2),
contactRepo.get(4)
]
);
var coworkers = new Collection(
contactRepo,
[
contactRepo.get(1),
contactRepo.get(2),
contactRepo.get(5)
]
);
contactRepo.items; // contains item ids 1, 2, 3, 4, 5
friends.items; // contains item ids 2, 4
coworkers.items; // contains item ids 1, 2, 5
coworkers.remove(2);
contactRepo.items; // contains item ids 1, 2, 3, 4, 5
friends.items; // contains item ids 2, 4
coworkers.items; // contains item ids 1, 5
friends.remove(4);
contactRepo.items; // contains item ids 1, 2, 3, 5
friends.items; // contains item ids 2
coworkers.items; // contains item ids 1, 5
注意 coworkers.remove(2)
如何沒有從 contactRepo 中刪除 id 2?這是因為它仍然被 friends.items
引用.但是,friends.remove(4)
會導致 id 4 從 contactRepo
中刪除,因為沒有其他集合引用它.
Notice how coworkers.remove(2)
didn't remove id 2 from contactRepo? This is because it was still referenced from friends.items
. However, friends.remove(4)
causes id 4 to be removed from contactRepo
, because no other collection is referring to it.
以上是我想做的.我確信有辦法通過跟蹤我自己的引用計數器等來做到這一點.但是如果有辦法使用 javascript 的內置引用管理來做到這一點,我想聽聽如何使用它.
The above is what I want to do. I'm sure there are ways I can do this by keeping track of my own reference counters and such. But if there is a way to do it using javascript's built-in reference management, I'd like to hear about how to use it.
推薦答案
不,不,不,不;是的,如果你真的需要計算引用,你將不得不手動進行.JS 沒有 this、GC 或弱引用的接口.
No, no, no, no; and yes, if you really need to count references you will have to do it manually. JS has no interface to this, GC, or weak references.
雖然您可以實現手動引用計數對象列表,但是否所有額外開銷(在性能方面,但更重要的是代碼復雜性)是否值得值得懷疑.
Whilst you could implement a manual reference-counted object list, it's questionable whether all the extra overhead (in performance terms but more importantly code complexity) is worth it.
在您的示例代碼中,忘記 Repository
似乎更簡單,為列表使用普通的 Array
,并讓標準垃圾收集處理丟棄未使用的人.如果您需要獲取所有在用人員的列表,您只需 concat
friends
和 coworkers
列表(并對它們進行排序/唯一化如果需要).
In your example code it would seem simpler to forget the Repository
, use a plain Array
for your lists, and let standard garbage collection take care of dropping unused people. If you needed to get a list of all people in use, you'd just concat
the friends
and coworkers
lists (and sort/uniquify them if you needed to).
這篇關于如何獲取 javascript 對象引用或引用計數?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!