Czy obiekty/zmienne JavaScript mają jakiś unikalny identyfikator? Podobnie jak Ruby ma object_id
. Nie mam na myśli atrybutu DOMID, ale raczej jakiegoś rodzaju adresu pamięci.Identyfikator obiektu JavaScript
Odpowiedz
Nie, obiekty nie mają wbudowanego identyfikatora, ale można go dodać, modyfikując prototyp obiektu. Oto przykład tego, jak można to zrobić:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
To powiedziawszy, w ogóle modyfikując prototyp obiekt jest za bardzo złą praktyką. Zamiast tego zaleciłbym ręczne przypisanie identyfikatora do obiektów w razie potrzeby lub użycie funkcji touch
, tak jak sugerowali inni.
ActionScript 3 ma obiekt Dictionary, który używa ścisłej równości do porównywania kluczy, więc można używać obiektów jako kluczy. Czy istnieje odpowiednik w JavaScript, czy musiałbyś ręcznie skonstruować unikatowe identyfikatory dla każdego obiektu (poprzez Object.prototype lub ręcznie dodając identyfikator do wybranych obiektów)? – Triynko
Niestety javascript nie ma czegoś takiego. Wygląda na to, że będziesz musiał podać id obiektów, a następnie użyć tych identyfikatorów jako kluczy w obiekcie, tak jak sugerujesz. To powiedziawszy, jeśli naprawdę chcesz być sprytny, możesz zaimplementować "obiekty id" poprzez przesłonięcie metody 'toString' i użycie ich w ten sposób' id = new Id(); cache [id] = obj'. To trochę orzechowe, ale całkiem interesujące. Oto artykuł, który napisałem, który wyjaśnia tę technikę bardziej szczegółowo: http://xavi.co/articles/fun-with-tostring-in-javascript – Xavi
OK, właśnie dowiedziałem się, dlaczego. jQuery nadpisuje również ID i jakoś moja strona się zepsuła, kiedy ją przejąłem. Hah. W porządku. Więc. Po prostu uniknę problemów z nazywaniem i przekreślam palce. – Lodewijk
W rzeczywistości nie trzeba modyfikować prototypu object
. Następujące rzeczy powinny działać, aby "uzyskać" niepowtarzalne identyfikatory dla dowolnego obiektu, wystarczająco skutecznie.
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;
}
Pamiętaj, że to NIE będzie dobrze grać z większością sposobów kopiowania obiektów, jeśli spodziewasz się, że obiekty będą później miały różne identyfikatory. –
Rzeczywiście, potrzebowałbyś specjalnej funkcji "copyObject", która bierze to pod uwagę __obj_id specjalnie. Trzeba też mieć pewność, że nie ma konfliktów w korzystaniu z "__obj_id" w innych bibliotekach. Jest to znacznie łatwiejsze w języku ActionScript, którego obiekt Dictionary używa ścisłego porównania równości na kluczach, w tym obiektach używanych jako klucze. W rzeczywistości prawdopodobnie można napisać klasę Dictionary w JS, która automatycznie dołącza ids w ten sposób do obiektów, które są do niej dodawane jako klucze. To jak kwantowe mechanizmy JavaScript ID; nie istnieją, dopóki nie spróbujesz ich obserwować z tą funkcją, haha. – Triynko
Właśnie się z tym spotkałem i pomyślałem, że dodam swoje myśli. Jak inni sugerują, polecam ręczne dodawanie identyfikatorów, ale jeśli naprawdę chcesz coś podobnego do tego, co opisałeś, można użyć to:
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;
})();
można uzyskać identyfikator dowolnego obiektu poprzez wywołanie objectId(obj)
. Następnie, jeśli chcesz, id być właściwością obiektu, można przedłużyć prototype:
Object.prototype.id = function() {
return objectId(this);
}
lub można ręcznie dodać identyfikator dla każdego obiektu poprzez dodanie podobną funkcję jako metodę.
Najważniejszym zastrzeżeniem jest to, że zapobiegnie to niszczeniu obiektów przez przedmioty znajdujące się w odpadach podczas ich opuszczania ... nigdy nie znikną one z zakresu tablicy allObjects
, więc może być problem z wyciekami pamięci. Jeśli twój zestaw używa tej metody, powinieneś zrobić to tylko dla celów debugowania. W razie potrzeby możesz wykonać objectId.clear()
, aby wyczyścić allObjects
i pozwolić GC wykonać swoje zadanie (ale od tego momentu wszystkie identyfikatory obiektów zostaną zresetowane).
myślę jest powolny, ale odpornego rozwiązanie i może być poprawiona trochę: '' var objectid = (funkcja() { var mem = []; var f = funkcja (obj) { var R = mem.indexOf (obj) if (R === 1) {R = mem.length; mem.push (obj) } powrotnym R; }; f.reset = function() { return mem = []; }; return f; })(); '' ' – luochen1990
@ luochen1990, Myślę, że byłbyś zaskoczony szybkością tego. (Ale masz rację, lepiej jest umieścić indeks indexOf() w zmiennej, chociaż argumentowałbym to raczej z perspektywy DRY niż optymalizacji). Tak długo, jak kwestię GC można skutecznie zarządzać, myślę, że " Musimy mieć dużo przedmiotów, aby zauważyć jakikolwiek znaczący wpływ na wydajność. –
Jeśli chcesz odnośnika/skojarzyć obiekt z unikalnym identyfikatorem bez modyfikowania podstawowych obiektów, można użyć 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
Używanie WeakMap
zapewnia, że obiekty mogą być nadal śmieci zebrane.
Najlepsza odpowiedź! Używa pamięci O (n), gdzie n jest liczbą obiektów, których identyfikatory Cię interesują (a nie n = wszystkie obiekty) i nie wpływa na odśmiecanie. –
Czy chcesz porównać obiekty przy użyciu id_obiektu? – Upperstage
Zobacz http://stackoverflow.com/questions/1997661/unique-object-identifier-in-javascript –