자바스크립트의 자료형 (문자, 숫자, array, object 등)은 자료형을 크게 2개로 분류한다.
Primitive & reference라고 분류하는데
Primitive data type들은 그냥 별건 없고 자료 자체가 변수에 저장되는 자료들이다.
문자, 숫자 자료형들이 대표적인 primitive data type들이다.
let name = 'john';
let age = 20;
이렇게 문자나 숫자 자료형은 문자나 숫자가 변수에 직접 저장된다는 소리이다.
Array, Object 자료형은 reference data type에 속한다.
reference data type은 자료를 변수에 직접 저장하는게 아닌,
자료가 저쪽에 있습니다 라는 화살표 (레퍼런스)를 변수에 저장한다.
예를 들어보자.
let person = { name : 'Kim' };
방금 { name : 'Kim' } 이라는 자료를 변수에 저장했다.
하지만 변수에 저장된건 { name : 'Kim' } 이게 아니다.
"{ name : 'Kim' }이 저기 저장되어있습니다"라는
{ name : 'Kim' } 값을 가리키는 화살표가 저장이 되어있을 뿐이다.
Kim이라는 데이터가 변수에 저장된게 아니다. Kim이라는게 저기 있습니다~ 라는 정보만 저장할 뿐이다.
그래서 이런 reference만 저장되는 array, object 자료형을 reference data type이라고 한다.
Q. 화살표가 가리키는 저기가 어딘데?
A. 컴퓨터 메모리 상의 어떤 곳이다.
그냥 우리는 컨트롤할 수 없는 미지의 공간이라고 생각해도 된다.
C언어 배운 사람들은 포인터인가? 라고 생각할 수 있는데 비슷하다.
다만 C언어처럼 포인터 주소같은 개념은 다루지 못힌다.
아무튼 그래서reference data type은 신기한 현상들이 일어난다.
한번 아주 직관적이고 간단한 Primitive 자료형부터 복사해보자.
let name1 = '김';
let name2 = name1;
name1 = '박';
(1) name1은 '김'이라는 문자를 집어넣었고
(2) name2는 name1에 있던 자료를 복사해서 집어넣었다. (등호는 그냥 집어넣는다라는 뜻이다 같다는게 아님!)
(3) 셋째줄에서 name1을 박으로 변경했다.
그럼 name1, name2를 출력하면 각각 무엇이 나올까?
name1은 변경했으니 '박'이고, name2는 복사만했지 변경하진 않았으니 '김' 이다.
별로 이상한 점이 없다.

근데 똑같은 일을 reference data type으로 진행하면 이상한 일이 일어난다.
한번 Reference 타입 자료형인 object를 이용해 똑같이 해보자.
let name1 = { name : '김' };
let name2 = name1;
name1.name = '박';
(1) name1은 { name : '김' } 이라는 object자료형을 집어넣었고
(2) name2는 name1에 있던 자료를 복사해서 집어넣었다.
(3) 셋째줄에서 name1 object 안의 name을 박으로 변경했다.
그럼 name1, name2를 출력하면 각각 무엇이 나올까?
name1은 변경했으니 { name : '박' } 이고, name2는 복사만했지 변경하진 않았으니 { name : '김' } 이다.
근데 콘솔창에 출력해보면 아니라고 한다?

둘다 { name : '박' } 이었다!
분명 코드를 보면
let name1 = { name : '김' };
let name2 = name1;
name1.name = '박';
name1는 우리가 값을 전혀 수정한 적이 없는데 바뀌어있다.
왜 그러냐면.. 두번째줄이 문제이다.
name2에 name1을 복사해서 집어넣을 때가 문제이다.
이 때, name1에 있던 { name : '김' } 이라는 데이터가 복사된게 아니다.
왜냐면 name1에는 {} 이게 저장된게 아니라 reference (화살표)가 저장되어있다고 했으니까!
name1의 화살표를 name2에 복사한것이다.
이제 name1과 name2는 같은 화살표를 가지고 있다.
그림으로 표현하자면 이렇다.

name1과 name2는 같은 화살표 (reference) 를 가지게 된 것이고
그 화살표는 { name : '김' } 이라는 같은 값을 가리키고 있는 것일 뿐이다.
그럼 아까 코드에서 셋째줄에서 name1.name = '박' 이렇게 값 변경을 하면 어떻게 될까?
화살표를 타고 들어가서 name 을 '박'으로 설정해준다.
근데 가만히 있던 name2를 출력해보면
화살표를 타고 들어가서 { name : '박' } 이라는 데이터가 나오게 되는 것이다.
이런 원리 때문에 name1과 name2는 같은 값을 공유하고 있었던 것이다.
결론은 object, array 자료형은 등호로 복사하면
화살표 값을 공유해버리기 때문에 문제가 일어날 수 있다.
그래서 다음시간에 배울 constructor 문법을 써서 object를 복사하면 안전하다.
새로운 {} object를 할당할 때마다 화살표가 새로 생성된다고 보면 된다.
정확한 명칭은 reference 지만 기억에 오래 남게 화살표라고 하자!
let name1 = { name : '김' };
let name2 = { name : '박' };
지금 첫줄과 둘째줄 모두 object를 새로 할당해주고 있다.
object가 저기 있다는 화살표를 할당해준 것이다.
그럼 이걸 한번 보자.
let name1 = { name : '김' };
let name2 = { name : '김' };
지금 첫줄과 둘째줄 모두 object를 새로 할당해주고 있다. 근데 object 안의 내용이 똑같다.
여기서 문제풀어보자!
Q. 바로 위의 예제에서 name1 == name2 이렇게 두개를 같다고 비교하면 true가 나올까요 false가 나올까?
뭘까
A. false가 나온다.
왜그럴까?
왜냐면
name1과name2에 저장된건 데이터가 아니라화살표이다.
==등호로 비교하고 있는건 지금object두개가 아니다. 화살표 두개이다.
화살표가 같으면 (같은 곳을 가리키면)true가 나오고, 화살표가 같지 않으면false가 나오기 때문이다.
위의 예제코드를 그림으로 표현하자면 이렇다.
각각 다른 화살표를 가지고 있기 때문에name1과name2는 같지 않다.
array도 마찬가지이다. 함부로 같다고 비교하시면 안된다.
굳이 값이 같은지 비교하고 싶으면 name1.name과 name2.name을 비교해보자.
object를 = 등호를 이용해 조작하면 뭔가 일이 일어나는거 같으니까
이번엔 한번 함수를 이용해서 object 조작 기계를 만들어보자.
let name1 = { name : '김' };
function change(obj){
obj = { name : 'park' };
}
change(name1);
change() 이라는 함수를 만들었는데,
이 함수는 뭔가 object를 입력하면 object 내용을 { name : 'park' } 으로 재할당해주는 함수이다.
그래서 name1을 집어넣어서 실행해봤다.
Q. 근데 실행해봐도
name1은 바뀌지 않는다. 왜 그럴까?
답
왜그러냐면 여러분 함수 만들 때 파라미터라는것을 만든다.
파라미터는 일종의 변수처럼 생성되고 사라지는 존재라고 보시면 된다.
그냥 쉽게말하면var변수이다.
(인간의 시점)
let name1 = { name : '김' };
function change(obj){
obj = { name : 'park' };
}
change(name1);
(자바스크립트의 시점)
let name1 = { name : '김' };
function change(obj){
obj = { name : 'park' };
}
change(var obj = name1);
자바스크립트가 파라미터를 만들고 사용할 땐 대충 맨 밑줄처럼 만든다고 생각하면 된다.
(실제 이런 문법이 있는건 아니다!!)
obj라는 파라미터자리에 name1이라는 변수를 집어넣으면
var obj = name1 이렇게 파라미터형 변수를 만든것이다.
let name1 = { name : '김' };
function change(obj){
obj = { name : 'park' };
}
change(name1);
생각해보니 위 코드 패턴은 계속 보던 패턴이다.
obj 라는 변수에 name1이라는 { object } 를 등호로 복사해서 넣으면 어떻게 될까?
obj, name1 이 두개 변수는 서로 같은 화살표를 갖게 되며 { name : '김' } 값을 공유한다.
그런데 함수 내부를 잘 보면 obj라는 변수는 obj = { name : 'Park' } 이렇게 재할당을 해주고 있다.
이것은
obj라는 변수에 새로운 화살표를 재할당을 한 것이지
실제 name1이라는 변수는 전혀 건드리지 않고 있다.
그래서 결국 name1`은 바뀌지 않는 것이다.
Q. 그럼 밑의 예제코드는 실행하면 콘솔창에 무엇이 출력될까??
let name1 = { name : '김' };
function change(obj){
obj.name = 'park';
}
change(name1);
console.log(name1);

객체 생성 및 함수 호출
name1 객체를 생성하고 name 속성을 '김'으로 설정한다.change 함수를 호출하면서 name1 객체를 인수로 전달한다.함수 내부 동작 (change 함수)
change 함수의 매개변수 obj는 name1 객체를 참조한다.obj.name을 'park'로 변경한다.객체 출력:
console.log(name1);을 실행하여 name1 객체를 출력한다.실행 결과는 다음과 같다.
{ name: 'park' }
name1 객체는 { name: '김' }로 초기화되었다.change 함수가 호출될 때 name1 객체를 인수로 전달했다. 이는 자바스크립트에서는 객체를 참조로 전달하기 때문에, 함수 내에서 obj.name의 변경은 name1 객체에도 반영된다.change 함수 내에서 obj.name = 'park';을 실행하면 name1 객체의 name 속성 값이 '김'에서 'park'으로 변경된다.console.log(name1);을 실행하면 변경된 { name: 'park' }이 출력된다.자바스크립트로 학생 리스트를 만들어야한다.
let student1 = { name : 'Kim', age : 15 };
let student2 = { name : 'Park', age : 15 };
...
이렇게 쭉 30명을 만들어야한다. 어떻게 하는게 가장 빠른 방법일까?
object를 직접 중괄호쳐서 하드코딩 30개 하는 것 보다는
비슷한 object들이니 복사를 하는게 좋을 것 같다.
근데 = 등호를 이용해서 let student2 = student1 복사하면 큰일나니
object를 복사해서 찍어낼 수 있는 새로운 문법을 이용해보자.
//let student1 = { name : 'Kim', age : 15 };
function machine(){
this.name = 'Kim';
this.age = 15;
}
object 자료 복사 machine만들 땐 function이라는 함수만드는 키워드를 빌려서 이용하면 된다.
function을 하나 만들고 거기 안에 this.name과 this.age를 집어넣어주면 된다.
이게 바로 object 생성 기계이다.
this는 새로생성되는 object를 뜻한다. (그걸 멋진 개발용어로 인스턴스라고 한다)
this에 대해 더 알아보기
Q. 그렇다면 this.name = 'Kim' 이 뭔소리일까?
object자료 추가/수정문법이다.
새로생성되는object.name은'Kim'을 넣어주세요~라는 뜻이다.
이제 기계에서 새로운 object를 뽑고 싶으면 이렇게 따라하면 된다.
function machine(){
this.name = 'Kim';
this.age = 15;
}
let student1 = new machine();
let student2 = new machine();
new라는 키워드를 사용한 다음 오른쪽에 machine(constructor 함수) 이름을 쓰면
machine로부터 새로운 object를 하나를 뽑아낼 수 있다.
그리고 그걸 변수에 저장하면 이제 자유롭게 object를 뽑아 쓸 수 있다.
비슷한 + 독립적인 object 자료를 여러개 만들 때 코드의 양이 줄어든다.
그래서 사용하는 문법이다.
특히 object안에 들어갈 내용이 복잡하고 많을 때 사용해야한다.
함수도 object에 추가할 수 있.
그니까 예를 들면 모든 학생 object 안에 sayHi() 라는 함수를 추가해야한다고 예시를 들어보자.
student1.sayHi()라고 사용하면 콘솔창에 "안녕하세요 'Kim'입니다"라고 이름이 포함된 인삿말을 출력해주어야한다.
어떻게 코드를 짜면 될까?
let student1 = {
name : 'Kim',
age : 15
sayHi : function(){
console.log('안녕하세요' + this.name + ' 입니다');
}
};
student1.sayHi();
이렇게 하면 되겠군요. (함수 안의 this.name이 뭔지 궁금하다면 this에 관한 이전 강의를 살펴보자)
object 자료형 내에 함수들이 있을 수 있는데 거기서 this값은 '주인님'을 뜻한다.
근데 student1이라는 곳에다가만 하드코딩하는게 아니라
앞으로 모든 학생들이 sayHi()를 쓸 수 있게 만들고 싶으면 어떻게 해야할까?
당연히 object 생성 기계에 추가하시면 된다.
machine에 sayHi()를 추가해보자.
function machine(){
this.name = 'Kim';
this.age = 15;
this.sayHi = function(){
console.log('안녕하세요' + this.name + ' 입니다');
}
}
let student1 = new machine();
let student2 = new machine();
student2.sayHi();
machine에 저렇게 this.sayHi 를 추가하면 이제 machine로부터 생성되는 모든 학생들이 sayHi()를 가지고 있게 된다.
그럼 student1, student2 전부 sayHi()를 쓸 수 있게된다.
지금까지 뽑은 object들의 문제가 있다.
student1이나 student2나 name이 똑같은 것을 볼 수 있다. 실용성이 없다.
그렇다면 실제 name 속성을 각각 다르게 해서 뽑고싶으면 어떻게 해야할까?
그것은 함수엔 파라미터를 추가할 수 있음을 떠올리면 된다.
function machine(personName){
this.name = personName;
this.age = 15;
this.sayHi = function(){
console.log('안녕하세요' + this.name + ' 입니다');
}
}
let student1 = new machine('Park');
let student2 = new machine('Kim');
함수에 파라미터를 추가한다면 앞으로 machine라는 함수를 쓸 때마다
파라미터자리에 뭔가 데이터를 넣어서 실행할 수 있는 것이다.
▲ 그래서 마지막줄 보시면 machine()를 쓸 때 데이터를 넣어봤다.
그 'Park' 이라는 데이터는 파라미터자리에 쏙 들어가서 함수가 실행되게 되며
그럼 새로 생성되는 object의 name속성은 'Park'이 된다. (this.name = 'Park')
그럼이제
student1은 { name : 'Park', age : 15 }
student2는 { name : 'Kim', age : 15 }
이렇게 출력된다.
생성되는 object마다 각각 다른 값을 부여하고 싶다면 저렇게 함수의 파라미터를 이용해야한다.
age도 바꾸고 싶다면 파라미터를 한개 더 추가하면 될 것 같다.
그래서 하드코딩해봤는데
let product1 = { name : 'shirts', price : 50000 };
let product2 = { name : 'pants', price : 60000 };
앞으로 몇십개를 더 만들어야해서 하드코딩은 그만두고 constructor를 만들어서 object를 뽑아내려고 한다.
Q1. 위처럼 생긴 상품오브젝트들을 뽑아낼 수 있는
constructor를 제작해보자.풀이
1. machine constructor 생성
function testMachine() {}2.
this키워드를 사용해object생성function testMachine() { this.name = "shirts"; this.price = 60000; }3.
object마다 각각 다른 값을 부여해야하니 파라미터 사용function testMachine(personName, productPrice) { this.name = personName; this.price = productPrice; }
Q2. 그리고 실제 상품 두개를 뽑아보세요.
풀이
1.
new키워드를 사용하여object뽑아내기function testMachine(personName, productPrice) { this.name = personName; this.price = productPrice; } let product1 = new testMachine(); let product2 = new testMachine();1-1. 현재 파라미터로 값을 받고 있으니 argument를 통해 값 넘겨주기
function testMachine(personName, productPrice) { this.name = personName; this.price = productPrice; } let product1 = new testMachine('shirts', 50000); let product2 = new testMachine('pants', 60000);2. 각 각 product1, product2 상품 및 가격 뽑아내기
function testMachine(personName, productPrice) { this.name = personName; this.price = productPrice; } let product1 = new testMachine('shirts', 50000); let product2 = new testMachine('pants', 60000); console.log(`상품: ${product1.name} 가격: ${product1.price}`); console.log(`상품: ${product2.name} 가격: ${product2.price}`);
Q3. 상품마다 VAT() 라는 내부 함수를 실행하면 콘솔창에 상품가격 * 10% 만큼의 부가세금액이 출력되도록 하고 싶으면constructor를 어떻게 수정해야할까?
예를 들면
product1.VAT()이렇게 쓰면 콘솔창에5000이 출력되어야한다.풀이
function testMachine(personName, productPrice) { this.name = personName; this.price = productPrice; this.VAT = function () { console.log(this.price * 0.1); }; } let product1 = new testMachine("shirts", 50000); let product2 = new testMachine("pants", 60000); // console.log(`상품: ${product1.name} 가격: ${product1.price}`); // console.log(`상품: ${product2.name} 가격: ${product2.price}`); product1.VAT();