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

„Odświeżanie” wartości zdefiniowanych zmiennych

Object Storage Arubacloud
+1 głos
293 wizyt
pytanie zadane 30 września 2016 w JavaScript przez marcin.1993 Początkujący (320 p.)
edycja 30 września 2016 przez marcin.1993

Cześć

Mam sobie taki oto prosty kodzik:

function addInputs(btn, target) {
    var id = 1;
    
    var dateId = "date" + id;
    var matchId = "match" + id;
    
    [...]

    btn.addEventListener("click", function(){
        id++;
        
        
        console.log(dateId); //wyrzuca „date1” mimo inkrementacji
        
    })
}

Chciałbym, żeby po id++ zmieniały się wartości zmiennych dateId i matchId. Wiem, że jeżeli zdefiniuję te zmienne po inkrementacji to wtedy zadziała wszystko dobrze, ale czy jest jakiś bardziej elegancki sposób, żeby niejako „odświeżyć” wartości tych zmiennych bez ich ponownego definiowania?

Z góry dzięki za pomoc. :)

2 odpowiedzi

+4 głosów
odpowiedź 30 września 2016 przez ScriptyChris Mędrzec (190,190 p.)
wybrane 1 października 2016 przez marcin.1993
 
Najlepsza

console.log(dateId); //wyrzuca „date1” mimo inkrementacji

W JavaScript dane typu primitive przekazywane są poprzez kopię a nie referencje (jak w przypadku obiektów) - co oznacza, że jeśli przypiszesz wartość zmiennej A do zmiennej B, po czym zmienisz zmienną A, to zmienna B pozostanie nietknięta (kopiowanie nie mutuje zmiennej).

http://www.2ality.com/2011/03/javascript-values-not-everything-is.html

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

Przykład:

var a = 2;
var b = a;

a = 4;

console.log( a ); // 4
console.log( b ); // 2

Tworzysz zmienną, potem przypisujesz jej wartość do innej zmiennej, zmieniasz wartość pierwotnej zmiennej a zmienna, do której ją przypisałeś nie zmienia swojej wartości.

Co innego, gdy zrobisz podobnie na obiekcie:

var obj = { name: 'John' };
var clonedObj = obj;

obj.name = 'Ben';

console.log( obj ); //  { name: "Ben" }
console.log( clonedObj ); //  { name: "Ben" }

Tutaj mamy do czynienia z mutacją, czyli zmianą wartości (właściwie to pola, bo działamy na obiekcie).

To samo dotyczy tablic, które są elementami obiektopodobnymi (obiektopodobne, bo mają swoje metody, ale w tablicy poruszasz się po indeksie - obiekt "udostępnia" Ci klucz):

var arr = [ 1, 2, 3 ];
var clonedArr = arr;

arr[ 2 ] = 8;

console.log( arr );  // [1, 2, 8]
console.log( clonedArr ); // [1, 2, 8]

Również tutaj, zmieniasz "wnętrzności" tablicy zarówno dla pierwotnie przypisanej zmiennej, jak i tej pomocniczej.

Co do Twojego pytania - jeśli chcesz zinkrementować wartość liczbową, a następnie ją przypisać do stringa, to w wyniku konkatenacji otrzymasz Twoją zmienną np. "wiek10" + 6 = "wiek106". Mógłbyś najpierw wydłubać liczbę ze swojej zmiennej - zinkrementować ją, bądź zmienić wartość i z powrotem ją w tym wyrazie umieścić, czyli:

var num = 10;
var age = 'wiek' + num;

var firstNumIndex = age.split( '' ).findIndex( function( elem ) { // podziel stringa na pojedyncze znaki
  return Number( elem ); // zwroc pierwszy napotkany indeks, jesli to bedzie liczba
} );

age = age.slice( -age.length, firstNumIndex ); // usun liczbe, ktora zaczyna sie od znalezionego indeksu

num++; // inkrementuj

age += num; // dopisz zinkrementowana liczbe do pierwotnego wyrazu w zmiennej

console.log( age ); // "wiek11"

 

3
komentarz 1 października 2016 przez niezalogowany
edycja 1 października 2016

... najpierw wydłubać liczbę ze swojej zmiennej - zinkrementować ją, bądź zmienić wartość i z powrotem ją w tym wyrazie umieścić,

regExpString.prototype.replace + backreference

Zakładając, że liczba zawsze wystąpi na końcu:

age = age.replace( /(\d+)/, function( str , age ) {
  return ++age;
} );

W ES6 nawet łatwiej i przyjemniej, bo skraca się to rozwiązanie do jednej linii:

age = age.replace( /(\d+)/ , ( str , age ) => ++age );

lub korzystając z destructuring assignment:

age = age.replace( /(\d+)/ , ...a => ++a[ 1 ] );

Jednak wszystko powyżej to sposoby raczej barbarzyńskie - najlepiej stworzyć własny obiekt przystosowany do takich celów:

var age = {
  text: 'wiek',
  value: 10,
  get: function() {
    return this.text + this.value;
  },
  increment: function() {
    this.value++;
    return this.get();
  }
}

console.log( age.get() ); // wiek10
console.log( age.increment() ); // wiek11
console.log( age.increment() ); // wiek12
console.log( age.get() ); // wiek12

Kiedy takich 'inkrementatorów' potrzeba więcej, można pokusić się o stworzenie konstruktora (lub w ES6 - klasy)

komentarz 1 października 2016 przez ScriptyChris Mędrzec (190,190 p.)
Bardziej chciałem wytłumaczyć, dlaczego kod autora mu nie działa, niż pokazywać że można skorzystać z Regex i ES6 (z którego autor nie korzysta). W sumie z metodami na obiekcie też mogłem pokazać, no ale pokazałem "barbarzyńsko" :P

Fajnie, że odpowiedzi na forum są w jakiś sposób poddawane CodeReview, to od razu autor może sobie przyswoić mniej i bardziej optymalny sposób rozwiązania swojego problemu.
1
komentarz 1 października 2016 przez niezalogowany

Najpierw pokazałem w ES5, dopiero później to samo w ES6.

Wiesz co jest najlepsze? że w oryginalnym kodzie:

function addInputs(btn, target) {
    var id = 1;
     
    var dateId = "date" + id;
    var matchId = "match" + id;
     
    [...]
 
    btn.addEventListener("click", function(){
        id++;
         
         
        console.log(dateId); //wyrzuca „date1” mimo inkrementacji
         
    })
}

w 11 linijce wystarczy dodać:

dateId = "date" + id;

I wszystko zacznie działać : D

komentarz 1 października 2016 przez ScriptyChris Mędrzec (190,190 p.)

w 11 linijce wystarczy dodać:

Trzeba było dodać taką odpowiedź ;) A, już jest - poniżej mojej.

komentarz 1 października 2016 przez niezalogowany
Rzeczywiście :v welp..
komentarz 1 października 2016 przez marcin.1993 Początkujący (320 p.)
@niezalogowany, tak, mam świadomość tego, że to będzie działało, tylko w takim wypadku muszę dwa razy wklejać w zasadzie „taką samą” linijkę kodu i chodziło mi po prostu o to czy da się to zrobić w jakiś bardziej „ekonomiczny” sposób niż powielanie. ;) Dziękuję wszystkim za pomoc! :)
+2 głosów
odpowiedź 30 września 2016 przez Fenix Nałogowiec (26,750 p.)

Tak jest to możliwe, więcej na temat: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters

Jednak patrząc na Twój aktualny kod, oraz pytanie nie wydaję mi się abyś aktualnie był na poziomie pozwolającym korzystać z tych mechanizów. A więc najlepszym możliwym według mnie rozwiązaniem na Twoim obecnym poziomie, będzie uaktualnienie zmiennej w taki oto sposób 

  btn.addEventListener("click", function(){
        id++;
        dateId = "date" +id;
         
         
        console.log(dateId); //wyrzuca „date1” mimo inkrementacji
         
    })

 

 

Podobne pytania

0 głosów
0 odpowiedzi 73 wizyt
0 głosów
3 odpowiedzi 1,201 wizyt
0 głosów
1 odpowiedź 967 wizyt

92,632 zapytań

141,500 odpowiedzi

319,879 komentarzy

62,013 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...