• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed JS - jak usunąć obiekt

VPS Starter Arubacloud
0 głosów
2,795 wizyt
pytanie zadane 7 marca 2017 w JavaScript przez hoktaur Pasjonat (22,250 p.)
zamknięte 9 marca 2017 przez hoktaur

Załóżmy mam stworzoną tablice z obiektami:

var test = [];
test.push(new klasa());
test.push(new klasa());
test.push(new klasa());

i teraz ze względu na pewne warunki w metodzie danego obiektu przestaje mi on być potrzebny i chciałbym go usunąć  jak to zrobić?

Czytałem coś o fakcie że delete nie zadziała na sam obiekt i o garbage collector, ale nie bardzo wiem jak to zrobić?

 

 

komentarz zamknięcia: Problem rozwiązałem sam (link do rozwiązanie na samym dole w komentarzu), ale podpowiedzi były super .... THX
komentarz 9 marca 2017 przez rosomack Nowicjusz (160 p.)
cześć. zastanawiam się czy chcesz usunąć obiekt ogólnie z pamięci - "bo tak" czy usunąć go z arraya? bo, gdy to drugie to wystarczy `someArray.splice(x,1)`, gdzie `x` to indeks który chcemy usunąć, a 1 to ilośc obiektów które chcemy usunąć (można chcieć usunąć obiekty 2 o indeksie 2,3 - a wtedy `someArray.splice(2,2)`)

gdy nie wiesz jaki jest indeks obiektu który chcesz usunąć - metoda `indexOf` :)
komentarz 9 marca 2017 przez hoktaur Pasjonat (22,250 p.)
Problem był nie tyle z samym usunięciem elementu co z wyszukaniem odpowiedniej zmiennej (jej indexu) z poziomu metody obiektu podrzędnego ... zmiana myślenia oraz przebudowa większości kodu pomogła.

1 odpowiedź

+3 głosów
odpowiedź 7 marca 2017 przez ScriptyChris Mędrzec (190,190 p.)

W JavaScript nie możesz samodzielnie usunąć obiektu, zajmuje się tym GarbageCollector, o którym wspomniałeś. Działa on automatycznie, programista nie za bardzo ma wpływ na to kiedy GC uruchamia się i co wtedy usuwa. Możesz przypisać wartość null dla danego obiektu "podpowiadając" GC, że z niego nie korzystasz - wtedy go usunie.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

Operator delete usuwa propertisy danego obiektu a nie obiekty.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

 

komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)

Thx za odpowiedź ale to już właśnie przeczytałem dlatego o tym wspomniałem.

Ok, ale może od początku, natchniony:

CRUD w JS - edytowanie nie działa poprawnie

odpaliłem kompa i zacząłem klikać i wyklikałem takie coś:

<!DOCTYPE html>
<html lang="pl">
<head>
	<title></title>
	<meta charset="utf-8">
	<style>

	</style>
  
</head>
<body>
	<ul id="list1"></ul>
		
	<ul id="list2"></ul>
		
	<ul id="list3"></ul>
	
		
	<script>

		function countries(node, countriesDefault = '') {
			this.Default = countriesDefault;
			this.list = [];
			this.targetNode = document.getElementById(node);	

			this.handleEvent = function(event) {
				var listLastIndex = this.list.push(new country('')) - 1;
				this.list[listLastIndex].display(this.targetNode, 'li');
			}
			
			this.displayAll = function() {
				
				var defaultCountry;
				
				for(let defaultCountry of this.Default) {
					var listLastIndex = this.list.push(new country(defaultCountry)) - 1;
					this.list[listLastIndex].display(this.targetNode, 'li');
				}
				
				var optionElement = document.createElement('button');
				optionElement.innerHTML = 'Dodaj';
				this.targetNode.parentNode.insertBefore(optionElement, this.targetNode.nextSibling);
				this.targetNode.nextSibling.addEventListener('click', this);
			}
		}
		
		function country(name) {
			this.name = name;
			this.node;
			this.editMode = false;
			
			this.display = function(targetObj, targetElement) {
				var targetElement = document.createElement(targetElement);
				
				if(this.name) {
					targetElement.innerHTML = this.name;
				} else {
					targetElement.innerHTML = '<input type="text" placeholder="Wprowadź nazwę..." /><button type="submit">&radic;</button><button type="reset">Usuń</button>';
					this.editMode = true;
				}
				
				targetObj.appendChild(targetElement);
				
				this.node = targetObj.lastChild;
				this.node.addEventListener('click', this);
			};
			
			this.handleEvent = function(event) {
				if(this.editMode) {
					switch(event.target.type) {
						case 'submit':
							this.name = (this.node.firstChild.value).trim();
							this.countrySetRemove();
						case 'reset':
							this.countrySetRemove();
							break;
					} 
					
				} else {
					this.node.innerHTML = '<input type="text" value="' + this.name + '" placeholder="Wprowadź nazwę..." /><button type="submit">&radic;</button><button type="reset">X</button>';
					this.editMode = true;
				}
			};
			
			this.countrySetRemove = function() {
				if(this.name) {
					this.node.innerHTML = this.name;
					this.editMode = false;
				} else {
					this.node.remove();
					
				}
			}
		}
		

		
		(function() {
		var countriesList;
			
			countriesList = new countries('list1', ['PL', 'EU', 'DE', 'GB']);
			countriesList.displayAll();
			
			countriesList = new countries('list2');
			countriesList.displayAll();
			
			countriesList = new countries('list3', ['PL', 'EU', 'DE', 'GB', 'HU']);
			countriesList.displayAll();
			
			
			
		})();
	</script>
</body>
</html>

Problem jest gdy usunę dany element (li) z documentu

this.node.remove();

ale to jest efekt tylko wizualny w tablicy dalej znajduje się obiekt związany z elementem tzn. mam this.name = '' oraz this.node =  chyba undefined ;) ale jest i jak go teraz usunąć?

komentarz 7 marca 2017 przez ScriptyChris Mędrzec (190,190 p.)

Do usuwania elementów z tablicy służy metoda splice.

komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)
ok, rozumiem ... może inaczej, wiem jak skasować dane z tablicy zwykłej tylko nie wiem jak mam odwołać do tej konkretnej z metody obiektu klasy country która  znajduje się w tablicy obiektu countries?
komentarz 7 marca 2017 przez ScriptyChris Mędrzec (190,190 p.)

Mógłbyś doprecyzować co konkretnie chcesz usunąć?

var countriesList;
             
            countriesList = new countries('list1', ['PL', 'EU', 'DE', 'GB']);
            countriesList.displayAll();
             
            countriesList = new countries('list2');
            countriesList.displayAll();
             
            countriesList = new countries('list3', ['PL', 'EU', 'DE', 'GB', 'HU']);
            countriesList.displayAll();

W IIFE tworzysz zmienną countriesList, do której za każdym razem przypisujesz nowy obiekt, po czym go wyświetlasz w widoku. Wypisując zawartość tej zmiennej:

console.log( countriesList );

, otrzymuje się niemały obiekt, w którym poza metodami są dwie tablice: Default oraz list. Pierwsza, to tablica danych typu string, druga jest tablicą zawierającą obiekty. Czy z którejś z nich chcesz coś usunąć (co konkretnie?), czy chodzi o inne dane?

komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)
Ok obiekty klasy countries zawiera w sobie w tablicy obiekty country (wszystkie wypunktowania w danej liście) oprócz tego zawiera inne właściwości jak miejsce lokalizacji danej listy oraz przypisane domyślne punkty listy.

Obiekty country zawierają zawartość (nazwę) punktu (li) danej listy, jego położenie oraz czy jest w trakcie edycji. Do tego położenia zostaje przypisany event 'click' żeby obsłużyć przyciski zatwierdź i anuluj oraz tryb wyświetlanie/edycja punktu. I na tym etapie jest wszystko ok.

Problem jest taki, kiedy nie wpiszemy nic lub są to znaki np. typu spacja punkt powinien być usunięty z widoku (to działa) oraz usunięty z tablicy danego obiektu klasy countries (to nie wiem jak zadeklarować do usunięcia). Sytuacja jest identyczna gdy dodajemy nowy obiekt conutry (klikamy przycisk 'dodaj') do tablicy obiektu countries wszystko się ładnie tworzy tylko jak znowu nic nie wpiszemy lub po naciśnięciu przycisku 'usuń' punkt powinien się usunąć (działa :) ) oraz usunąć się z tablicy obiektu coutries.
komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)
P.S. mógłby to mieć 'gdzieś' i stworzyć metodę w countries, która przed wykonaniem  innej metody sprawdzi zawartość czy tablica w obiekcie conutries zawiera takie obiekty country z name = '' lub node = undefined ale to według mnie jest obejście na około tematu i szukam lepszego rozwiązania ... po za tym musiałbym ją za każdym razem spr przed taki wykonaniem przy 3, 100 może 1000 nie będzie to miało wpływu na wydajność ale co jak tego będzie więcej więc wole posprzątać na bieżąco i mieć spokój no chyba że nie idzie?
komentarz 7 marca 2017 przez ScriptyChris Mędrzec (190,190 p.)
edycja 7 marca 2017 przez ScriptyChris

Nadaj każdemu elementowi listy atrybut id (najprościej w formie inkrementowalnej liczby, jak w bazie danych). W ten sposób przy usuwaniu będziesz mógł namierzyć **w liście node'ów** ten, którego id zgadza się z atrybutem id usuniętego z DOM elementu.

[edit]

Drobne sprostowanie (zamiast tego, co skreśliłem) => w tablicy (o nazwie list) obiektów (o nazwach country), które mają pole node.

Czyli mając w DOM listę node'ów z nadanymi atrybutami id, podczas usuwania sprawdzaj w tablicy list czy znajduje się obiekt, którego pole node zawiera to id.

komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)

No jest to jakieś rozwiązanie, normalnie bym się tak z tym nie ciaćkał tylko operowałbym w DOM'ie ale chciałem to ładnie w obiektówce zrobić, ale widzę kilka problemów:

- co jak country nie będzie już należeć do conutries tylko np klasy world albo np. tu i tu

- id powinno być jedyne w całym dokumencie a ja będę miał np. tak jak w przykładzie 3 listy każda w innym obiekcie countries 3 x id='1...x'

A jest możliwość żebym przekazał informację o obiekcie countries do country np.:

test.push(new country(this));

i potem się do tego odwołał w metodzie w country?

albo w metodzie country podczas kasowania wymusił spr. tabeli list?

 

komentarz 7 marca 2017 przez hoktaur Pasjonat (22,250 p.)
hmmm ... zastanawiam się jeszcze ... może gdzieś zrobiłem błąd koncepcyjny całej klasy?
komentarz 8 marca 2017 przez ScriptyChris Mędrzec (190,190 p.)

Wg mnie zaczynasz kombinować. Spróbuj z nadaniem atrybutu id. Aby było unikatowe, to nadawaj je w jakiejś formie np. "nazwaKlasy-0", "nazwaKlasy-1" itd., wtedy przy usuwaniu sprawdzaj czy element z listy posiada takie id jak ten, który kliknąłeś (przeznaczony do usunięcia) - jeśli tak, to usuwaj go z tablicy.

Co do zapisu:

test.push(new country(this));

, to musiałbyś zmodyfikować konstruktor dla klasy country (przy okazji, przyjęło się nazywać klasy z dużej litery), bo obecnie jako parametr przyjmuje name (czyli jakiś string), a Ty chcesz tam przekazać obiekt za pomocą wskaźnika this:

function country(name) {
     /**
       * funkcja będąca konstruktorem jako parametr przyjmuje 'name', 
       * ktory później używasz jako stringa do wstawiania wewnątrz elementów HTML, 
       * więc nie możesz tu przesłać obiektu w obecnej sytuacji
       */

      this.name = name;

      /** dalszy kod */
}

Spróbuj ewentualnie zrobić to w ten sposób:

test.push( new country( '' ).bind( this ) );

W momencie, gdy w JavaScript tworzysz obiekt za pomocą operatora new, kontekst this zostaje automatycznie ustawiony na ten obiekt. Żeby to zmienić, spróbuj zastosować metodę bind. Jako, że konstruktor w JS to tak na prawdę funkcja (funkcje w JS to też obiekty, tyle że z możliwością wywołania kodu), możesz zmienić jej kontekst wywoławczy na inny obiekt. Nie robiłem do tej pory czegoś takiego (zmiana kontekstu wywoławczego dla konstruktora), ale w teorii powinno działać.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/new

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Bound_functions_used_as_constructors

komentarz 9 marca 2017 przez hoktaur Pasjonat (22,250 p.)

Ok zrobiłem po swojemu bez id tylko z class'ami zmieniłem podejście i się udało, a moje rozwiązanie znajdziecie tutaj

THX za pomoc :)

Podobne pytania

0 głosów
2 odpowiedzi 2,830 wizyt
pytanie zadane 20 grudnia 2017 w Systemy operacyjne, programy przez niezalogowany
0 głosów
2 odpowiedzi 10,050 wizyt
0 głosów
1 odpowiedź 1,981 wizyt

93,078 zapytań

142,041 odpowiedzi

321,445 komentarzy

62,423 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...