Proslijediti po referenci ili vrijednosti
Vrijednosti u JavaScript-u su uvijek odredjenog tipa. Primitivni tip podataka su najsonovniji oblici vrijednosti (string
, number
, bigint
, boolean
, null
, undefined
, symbol
) i oni se proslijede po vrijednosti / kopira se podatak.
Sa druge strane, svi objekti (kao obicni objekti, nizovi i funkcije) se proslijede po referenci / ne radi se o kopiji.
Sta to znaci?
Primitivni podaci se prosljedjuju po vrijednosti jer varijabla sadrzi sam podatak (kao broj ili tekst), dok se objekti prosljedjuju po referenci jer varijabla u sebi drzi referencu / adresu na kojoj se podatak nalazi.
let a = 7;
let b = a; // prosljedjivanje vrijednosti
b = b + 8; // b = 15; a = 7;
let c = {name: 'Jane'}; // kreiranje objekta
let d = c; // prosljedjivanje po referenci
d.lastName = 'Doe'; // objekat dobija novo svojstvo
console.log(c); // {name: 'Jane', lastName: 'Doe'}
Varijabla | Vrijednost | Adresa | Vrijednost | |
---|---|---|---|---|
a | 7 | / | 0x01 | {name: 'Jane', lastName: 'Doe'} |
b | 15 | / | ||
c | 0x01 | / | ||
d | 0x01 | / |
Vazi i obrnuto. Izmjena c
varijable bi promijenila d
varijablu kako obe pokazuju na istu vrijednost.
Medjutim, treba imati na umu da prijenos po referenci znaci da:
let obj1 = {} // 0x01
let obj2 = {}; // 0x02
console.log(obj1 == obj2); // false
console.log({} == {}); // false
// ali
let obj3 = obj1; // 0x01
console.log(obj1 == obj3); // true
Svaki put kada kreiramo objekat, on je zaseban i cuva se na novoj adresi. Tako {} == {}
je false
jer nisu identicni objekti (0x01 =/= 0x02
), dok obj1 == obj3
jesu jer imaju istu referencu (0x01
).
let c = {}; // 0x01
let d = c; // 0x01
d.name = 'Jane'; // 0x01 dobija novo svojstvo
d = {author: 'Joe'}; // 0x02 definisan je novi objekat
console.log(c); // {name: 'Jane'}
console.log(d); // {author: 'Joe'}
Znakom jednakosti je varijabli d
dodijeljen objekat {}
sa desne strane. c
i d
vise ne pokazuju na isti objekat i modifikovanje vrijednosti jedne varijable nece uticati na vrijednost druge.
Varijabla | Vrijednost | Adresa | Vrijednost | |
---|---|---|---|---|
c | 0x01 | / | 0x01 | {name: 'Jane'} |
d | 0x02 | / | 0x02 | {author: 'Joe'} |
Funkcija
Okolnosti u kojima se prijenos po vrijednosti i referenci jos primjenjuje je u funkcijama. Kroz argumente smo, u kodu ispod, funkciji proslijedili objekat i vrijednost 43.
let employee = {name: 'Jane'}; // 0x01
let a = 43;
function addAge(person, age) {
person.isOld = age;
// 0x01.isOld = 43;
}
addAge(employee, a); // 0x01, 43
console.log(employee); // {name: 'Jane', isOld: 43}
- Objekat nije primitivni tip podatka i prenosi se po referenci, te mu je dodano svojstvo
isOld
kroz adresu koja pokazuje gdje se nalazi objekat0x01
u memoriji. - Sa druge strane, varijabla
age
koja sadrzi podatak primitivnog tipa nije proslijedjena kroz referencu, vec je kopirana u funkciju i postoji samo lokalno.
Sta ako varijabli person
kojoj je proslijedjen objekat 0x01
dodijelimo novi objekat? Hoce li se globalni objekat employee
promijeniti?
let employee = {name: 'Jane'}; // 0x01
let a = 43;
function addAge(person, age) {
person = {age: age};
// 0x02 = {age: 43};
}
addAge(employee, a); // 0x01, 43
console.log(employee); // {name: 'Jane'}
person
vise nema referencu na 0x01
i kroz tu varijablu ne mozemo izmjeniti employee
objekat, samo lokalni person
objekat na lokaciji 0x02
.