''
, ""
, ``
로 문자열을 표현할 수 있다.
typeof
로 type을 확인할 수 있다.
문자열에서도 +, -가 가능하다.
'%'의 경우에는 나머지를 뜻하며 '-', '*', '/'의 경우에는NaN(Not a Number)
가 출력된다.
NaN
이란 'Not a Number'을 뜻하며 숫자가 아니라는 뜻이다.typeof NaN
을 찾아보니 'Number'라고 확인이 된다. 하지만NaN
의 뜻처럼 'Not a Number'를 뜻한다. type이 숫자(Number)인데 NaN이라고? 외워야한다. 정식적으로NaN
은 숫자(Number)다.
parseInt
또는Number
를 사용하여 변경해주면된다.parseInt
와 Number
을 사용하여 정수로 변경하였을 때parseInt
와 Number
의 차이점이 있다.
parseInt
는 소수를 입력했을 때 소수를 제외한 정수만 출력하고 정수와 문자가 입력되었을 때는 정수만 뽑아서 보여준다.
Number
는 소수를 넣었을 경우 소수가 출력되고 정수와 문자를 입력했을 때NaN
이 출력된다.
**
로 표현해주면 된다.
Infinity
의 경우에는 무한대를 말하는 것 type은Number
다.
true
또는 false
문자열이 아니기에 따옴표로 감싸면 안된다.
비교를 하였을 때 확인할 수 있다.
NaN
과NaN
의 경우에는 어떻게 비교를하든false
가 나온다
true
와 false
도 비교가 되며 문자열 또한 비교가 된다.
문자열의 경우에는 문자열 순위에 따라서 결정이된다. (특수문자도 포함)
charCodeAt
으로 확인이 가능하다.
문자열과 숫자(정수)를 비교했을 경우 문자열을 숫자로 변화하여 비교한다. 하지만 문자열의 문자일경우에NaN
을 출력하기에 비교했을 경우false
가 확인된다.
==
와 ===
는 값이 같은지 비교할 때 사용하지만 차이가 있다. ==
는 값만 비교하고 ===
의 경우에는 자료형까지 비교한다.
불 값은 논리 연산자(||, &&)를 다룰 때 많이 사용한다.
false
, ''(빈문자 열)
, 0
, NaN
, undefined
, null
, document.all
이렇게 7가지가 불 값으로 형 변환했을 때 false
가 됩니다. 값이 false
라고 생각하면된다.
undefined
와 null
이 있다.undefined
는 반환할 값이 없을 경우 또는 기본값을 의미null
은 빈값을 의미 (undefined
와 같다) 대체적으로 일부러(?) 사용할 때 많이 사용한다.특정의 값을 저장하는 용도와 중복을 줄이기 위해서 사용
이렇게 변수에 담아서 언제든지 꺼내 사용가능하다.console.log
에서는undefined
가 출력이 되는데 이유는console.log
는 그림판이라고 생각하면 된다. 출력 전 잠시 보여주는 역할을 해주는 거기에 변수를 바로 입력했을 때와 출력값이 바로 도출되는거와 다르게undefined
가 뜬다.
변수를 선언하면(변수 선언문) 연산자의 우선순위로 인해+
먼저 계산 후 변수를 선언한 'c'에 대입이 된다. 'c'를 출력하면 600이라는 결과값이 나온다.
변수는 영어로 작성하는 걸 추천하며 띄어쓰기, 특수문자(몇가지 제외), 특정단어(javascript에서 이미 사용되는 단어), 첫글자 숫자를 제외해서 작성하도록한다.
변수에 선언한 값을 변경할 수 있다.
위에 이미지에 있는a = a + 3
과 같이 오른쪽의 내용을 왼쪽에 대입하는 방식으로 만들 수 있다.
/=
,-=
,+=
,*=
로 줄여서 사용할 수 있다.
var(variable)
을 사용하였지만 var의 문제점을 고쳐서 사용되고 있는 변수가let
이다. 현재는let
과const
의 변수로 충분히 활용하여 사용할 수 있다.
/*
if 조건문의 기본 형식 위에서 아래로 왼쪽에서 오른쪽으로 순차적으로 실행된다.
if(조건식)
동작문
*/
if(true){ //조건이 참(true)일 경우 밑에 동작문이 실행된다.
console.log('if 조건문'); //보여지는 문구
}
if(조건식){ //조건식이 참인 값일 때 실행
동작문;
} else{ //조건식이 거짓인 값일 때 실행
동작문;
}
if(조건식){
동작문;
} else if(조건식){
동작문;
} else{ // else if로 작성해도 됨
동작문
}
//중첩 if문
if(조건식){
동작문
if(조건식){
동작문
}
} else {
동작문
}
switch(조건식){
case 비교조건식 :
동작문
case 비교조건식 :
동작문
.
.
.
}
if문과 다르게 해당 조건식에 맞게되면 아래에 있는 내용도 전체 실행된다. 실행된 항목만 출력하고 싶으면break
를 작성해준다.
if문의else
와 같게 사용하는 방식으로default
가 있다.
default
는case
상단에 위치해도 됩니다.
'?'와 ':'로 한줄로 작성할 수 있음
괄호로 묶어주면 우선순위를 확인할 수 있어서 편하다.
거짓 부분에 중첩된 조건부 연산자가 있을 수 있다.
이 경우도 괄호로 묶어주면 우선순위를 좀 더 명확히 확인할 수 있다.
//기본 형식
while(조건식){ //조건이 true인 경우 아래의 동작문이 반복된다.
동작문1;
동작문2;
동작문3;
}
//예시
let i = 1 //변수 선언
while(i <= 100){
console.log(i); //변수값을 넣지않고 문자를 넣어주게되면 그 문자가 100번 찍힌다.
i++ // i = i + 1 또는 i += 1로 표현이가능.
}
결과값 100까지 출력하게된다.
실제 프로그래밍에서는 변수의 첫 값을 1을 넣기보다 0을 넣는다. 프로그래밍에서는 숫자를 0부터 세기 때문이다. 0부터 시작하는 경우의 조건식으로 바뀌면 아래와 같이 코드를 짤 수 있다.
let i = 0
while(i < 100){
console.log(i);
i++
}
결과값은 99까지 출력하게된다.
0부터 값을 세어주었기 떄문에 100번을돌면 99까지 출력하게된다.
//기본 형식
for(시작; 조건식; 종료식){
동작문;
}
//시작 -> 조건식 -> 동작문 -> 종료식 순으로 돌며 조건식 -> 동작문 -> 종료식 순으로 돈다.
//예시
for(let i = 0; i < 100; i++){
console.log('hello~');
}
결과값이다.
while문과 for문을 비교해보자
//while문
let i = 0;
while(i < 100){
console.log(i);
i++
}
//for문
for(let i = 0; i < 100 ; i++){
console.log(i);
}
let i = 0;
while(true){
if(i === 5) break;
i++;
}
console.log(i);
break
가 있기에 i가 5가되는 순간 break
로 빠져나오게된다. 출력되는 건 '5'가 출력된다.let i = 0;
while(i < 10){
i++;
if(i % 2 === 0){ //짝수만
continue; //건너뛰기
}
console.log(i);
}
continue
넘어갈 수 있도록 코드를 만들었다.for(let i= 0; i < 10; i++){
for(let j = 0; j < 10; j++){
console.log(i,j);
}
}
'9 9'까지 나오게된다.
for (let i = 0; i < 5; i++){
if ( i % 2 === 0 ) continue;
for (let j = 0; j < 5; j++){
if ( j % 2 === 0 ) continue;
for (let k = 0; k < 5; k++){
if (k % 2 === 0) continue;
console.log(i,j,k);
}
}
}
만약 같은 종류 예를 들어 과일이 있다고 생각하면 과일의 종류는 샐 수 없을만큼 많다 이것들을 하나하나씩 변수로 지정해서 변수 이름을 지정해주는 것은 어려운 일이다. 그렇기에 과일이라는 공통의 큰 의미가 있으면 이것을 배열로 사용해 값을 하나로 묶을 수 있다.
const fruits =['사과', '오렌지', '딸기', '수박']
요소
라고 칭한다. 각 배열에 있는 요소를 찾게 된다면 // 0 1 2 3 const fruits =['사과', '오렌지', '딸기', '수박'] //0부터 시작되며 index라고 부른다.
인덱스(index)
라고 칭하며 사과는 0번째인덱스 오렌지는 1번째인덱스... 각 요소에 입력된 값을 확인해보면
확인할 수 있다.
const arrayOfArray =[[1,2,3], [4,5]];
//배열의 내부에 배열이 들어 있으며 이것을 이차원 배열이라고 합니다.
const a = 10;
const b = 30;
const variableArrat = [a, b, 30];
//변수 또한 들어갈 수 있다.
const everything = ['사과', 1, undefined, true, '배열', null];
//모든 것을 넣을 수 있다.
const duplicated = ['가', '가', '가', '가', '가',];
//같은 값 또한 넣을 수 있다.
const empty = [];
//아무것도 안 넣어도 만들 수 있다.
.length
를 이용하여 배열의 요소의 개수 또한 확인할 수 있다.const everything = ['사과', 1, undefined, true, '배열', null];
console.log(everything.length)
위의everything
의 길이는 6이다. 요소의개수
의 길이는 6이고인덱스
는 0부터 5까지다. 마지막의 '인덱스'는 5이다.
요소의길이
- 1는 마지막 요소의 인덱스가 된다.
const everything = ['사과', 1, undefined, true, '배열', null];
console.log(everything[everything.length - 1])
//요소의 길이 6에서 1을 빼고 마지막 배열의 요소를 찾을 수 있다.
이렇게 배열의 마지막 요소를 찾을 수 있다.
const target = ['a', 'b', 'c', 'd', 'e'];
target[5] = 'f';
console.log(target)
이렇게 기존에 있던 배열의 마지막에 요소를 추가할 수 있다. 하지만 각 배열의 요소의 길이는 다르기 떄문에 다음과 같은 방식으로 배열의 마지막 부분에 요소를 추가할 수 있다.
const target = ['가', '나', '다', '라', '마'];
target[target.length] = '바';
console.log(target)
배열의요소
의 길이는인덱스
보다 1이 더 많기 때문에target.length
즉 요소의 길이를 이용해 마지막 요소를 추가할 수 있다.요소
의 길이는 1부터 계산하고인덱스
의 경우에는 0부터 계산하는 방식을 활용하였다. 하지만push
라는 기능을 이용하여 좀 더편하게 가장 마지막에 요소를 추가할 수 있다.
//push를 이용한 배열의 가장 마지막 추가
const target = ['가', '나', '다', '라', '마'];
target.push('바');
console.log(target)
이렇게push
를 이용해서 넣을 수 있다. 배열의 가장 마지막에 요소를 제거할 수도 있는데pop
을 이용하여 제거할 수 있다.
위처럼pop
을 이용하여 제거하였다.
unshift
라는 기능을 이용하여 넣을 수 있다.const target = ['b', 'c', 'd', 'e'];
target.unshift('a');
console.log(target);
가장 앞이라고target[0] = 'a';
라고 입력하게 된다면 가장 앞에있는 요소가 바뀌게된다. 이부분은 추가가 아닌 수정이된다.
위처럼 확인할 수 있다.push
와pop
처럼unshift
또한 짝이 있는데 가장 앞의 요소를 제거해주는shift
가 있다.
shift
를 활용하여 가장 앞의 요소를 제거하였다.
const
는 상수인데 상수는 바꿀 수 없다고 알고 있지만 여기서는 바꾸고 있다. 상수더라도 객체의 내부는 바꿀 수 있다.const
에는 새로운 값을 대입(=)하지 못한다고 생각하면 된다.const target2 = ['b', 'c', 'd', 'e'];
target2 = ['z', 'h']
//이렇게 객체의 전체를 변경하는거는 안된다.
target[0] = 'a'
//객체의 내부는 변경이 가능하다.
const target = ['가', '나', '다', '라'];
target.splice(1,1);
//첫번째는 인덱스를 두번째는 n번째까지 제거한다.
console.log(target);
이처럼 첫번째인덱스
의 첫번째까지 제거한다.const target = ['가', '나', '다', '라']; target.splice(2,3); //첫번째는 두번째 인덱스를 두번째는 3번째까지 제거한다. console.log(target);
두번째 인덱스에서 3번째까지 제거한다.
첫번째의 값만 넣어준다면 그 인덱스를 포함한 뒤쪽의 요소들 전체가 삭제된다.const target = ['가', '나', '다', '라']; target.splice(1); //첫번째의 값만 입력 console.log(target);
위처럼 첫번째의 인덱스를 포함한 뒤쪽 요소들이 제거되었다.
const target = ['가', '나', '다', '라', '마'];
target.splice(1, 3, '바','사');
// 첫번째 인덱스에서 첫번째 인덱스를 포함한 3번째까지 포함하여 제거 후 그 자리에 '바'와 '사'를 넣어준다.
console.log(target);
이처럼 중간에 제거한 요소의 위치에 요소를 넣을 수 있다. 요소를 제거하지 않고 중간에 요소를 추가 할 수 있다.'나'
와'다'
사이에'수박'
을 넣고 싶다면const target = ['가', '나', '다', '라', '마']; target.splice(2, 0, '수박'); // 두번째 인덱스를 포함한, 두번째 인덱스의 앞의 0번째(앞에) '수박'을 추가한다. console.log(target);
includes
를 통하여 요소를 찾을 수 있다.const target = ['가', '나', '다', '라', '마'];
const result = target.includes('다');
// 변수로 선언하여 target의 요소를 찾는다. '다'를 찾는다.
const result2 = target.includes('카');
// 변수로 선언하여 target의 요소를 찾는다. '카'를 찾는다.
/*
'다'의 경우에는 target의 배열에 요소로 있기 때문에 true가 되지만 '카'의 경우에는 target의 요소에
포함되어 있지 않기 때문에 false가 된다. 이것은 나중에 조건문 또는 반복문에서 많이 사용된다.
*/
console.log(result);
console.log(result2);
result는true
result2는false
로 확인할 수 있다.
includes
의 경우에는 배열에 요소가 있는지 확인하고 있으면true
없으면false
로 확인 할 수 있지만indexOf
와lastIndexOf
를 통해서 몇번째 인덱스의 자리에 있는지도 확인할 수 있다.const target = ['가', '나', '다', '라', '마']; const result = target.indexOf('다'); //'다'라는 요소가 앞에서부터 몇번째 인덱스에 있는지 const result1 = target.lastIndexOf('라'); //'라'라는 요소가 뒤에서부터 몇번째 인덱스에 있는지 const result2 = target.lastIndexOf('아'); //'아'라는 요소가 앞에서부터 몇번째에 인덱스에 있는지 console.log(result); console.log(result1); console.log(result2);
'아'
의 경우에는 target의 배열에 없기때문에 -1이 출력된다.
열
은 나열한다는 의미이며 반목문과 같이 사용되는 갑의 나열을 반복한다. 이렇게 생각하면 될 거 같다.while
과 for
문 모두 사용이 가능하다.//여기서 target이라는 배열의 요들을 전부 console.log로 찍도록 만들어보자
const target = ['가', '나', '다', '라', '마', '바'];
//배열을 만들고
let i = 0
// 배열에 포함된 요소를 전부 확인 할 수 있도록, 비교할 수 있도록 변수 하나를 만든다.
while(i < target.length){ //while 반복문을 통하여 확인할 수 있도록
//.length는 배열의 인덱스 보다 1 많기 때문에 i를 포함하지 않은 부등호표시 '<'로 확인
console.log(target[i]);
//i라는 변수가 각 요소의 인덱스 번호가 된다
i++;
//i = i + 1로 인덱스를 순서대로 확인할 수 있도록 만들어준다.
//for문으로 만들면
const target = ['가', '나', '다', '라', '마', '바']
for(let i = 0; i < target.length; i++){
console.log(target[i]);
}
배열에 있는 각 인덱스의 요소들을 확인할 수 있다. 역시나 문자열에서도 가능한데.//문자열에서도 가능한지 확인해본다 const target = '집에가고싶습니다.'; let i = 0 while(i < target.length){ console.log(target[i]); i++; }
이렇게 문자열의 길이 또한 알 수 있다.
//배열의 요소의 '라'를 모두 제거하시오
//모두의 경우에는 반복문을 이용하는 경우가 많다
const arr = ['가', '라', '다', '라', '마', '라']
arr.indexOf('라');
//indexOf로 '라'를 찾는다.
arr.splice(1, 1);
//찾은 인덱스(1) 위치를 삭제한다.
arr.indexOf('라');
//다시 indexOf로 '라'를 찾는다.
arr.splice(2, 1);
//찾은 인덱스(2) 위치를 삭제한다.
arr.indexOf('라');
//다시 indexOf로 '라'를 찾는다.
arr.splice(3, 1);
//찾은 인덱스(2) 위치를 삭제한다.
arr.indexOf('라');
//'라'가 아직까지 남아있는지 찾는데 있을경우 인덱스 번호가 나오고 없을경우 -1이 나온다.
이렇게 순서가 진행된다. 위의 반복되는 부분들이 보인다. 반복문을 만들어서 풀 수 있다.
const arr = ['가', '라', '다', '라', '마', '라']
while(arr.indexOf('라') > -1){ // !== 아닐 때 까지로 표현할 수도 있다.
//'라'가 있을 때 까지 반복됨
//'라'의 인덱스를 찾는다 true면 밑의 내용이 실행되고 아니면 빠져나온다.
arr.splice(arr.indexOf('라'), 1)
}
일정한 동작을 실행(호출)하는 것을 의미하며 함수를 만드는 방식은 크게 두가지로 나눠진다.
function(){}
과() => {}
이름을 붙여 사용하게된다.function a(){} //함수 선언문 //function 에서 직접 선언하는 방법 const b = function(){} //함수 표현식 //변수를 선언해서 사용하는 방법 const c = () => {} //화살표 함수 //화살표 함수의 경우에는 변수를 선언해서 무조건 실행하여야 한다.
이렇게 3가지 방식으로 사용된다.
function(){}
은 함수 선언문이라고 칭하고const a = function(){}
는 함수 표현식,const c = function(){}
는 화살표함수라고 칭한다.
선언한 함수를 실행(호출)하는 방법은a()
이렇게 실행(호출)하면된다.console.log()
나parseInt()
의 경우 뒤쪽에()
을 사용하는데 이것 또한 함수이기 때문이다.
이름을 붙이는 이유는 여러번 사용을 할 수 있게 만들어(저장)두기 위한 것이고 이름이 없는 함수를 익명함수라고 칭한다. 딱 1번만 사용할 경우 익명함수를 사용할 수 있다. 이렇게 함수를 만들어서 사용하는 이유는 반복으로 사용되는 코드의 양을 줄일 수 있기 때문이다.
return
어떤 반환 값을 얻을 때 쓰는 명령어 함수를 중단, 주어진 값을 함수 호출 지점으로 반환하며 기본 함수에서는return
이 빠져있다.문
과식
이 있는데식
의 경우에는 반환값이undefined
다.
반환 값이 없는게 아니라undefined
를 반환 한다라고 생각하면된다. 말하지만 사람들은 편하게 반환값이 없다고 하지만 정확하게undefined
를 반환하는거다.function a() { console.log('return이 빠져있습니다.') //마지막에 return의 작성은 뺄 수 있다. 원래 기본은 return undefined이며 undefined생략이 가능하다.
return
값을 직접 지정해줄 수 있다. 항상 함수의 마지막에는return undefined
가 생략되어 있다고 생각하면된다.
함수를 선언했을 때 반환값이 없는데 실행(호출)하면 반환값을 확인할 수 있다. 또한return
은 선언했을 때 함수를 종료해주는 역할을 한다. 그러므로 함수를 종료해주면서 반환을 한다.
그리고return
의 값을 여러개로 받고 싶으면 배열로 받으면된다function a() { return [1, 2]; }
함수를 선언할 때 매개변수(parameter) 함수를 호출할 때 인수(argument)
function a(parameter){ //함수를 선언할 때 매개변수(parameter)
console.log(parameter);
}
a('argument'); //함수를 호출할 때 인수(argument)
function a(w, x, y, z){
console.log(w, x, y, z);
console.log(arguments);
}
a('hello', 'parameter', 'argument')
매개변수와 인수가 짝지어져 연결된다. 'z'의 경우 연결되는 매개변수가 없기때문에undefined
가 연결된다.function
함수 안에서는arguments
를 사용할 수 있는데 호출할 때 넣었던 인수들이 뭐였는지 배열로 나열해준다. (단 화살표함수에는 사용할 수 없다.)
반대로 매개변수(parameter)의 개수가 적고 인수(argument)의 개수가 많을 경우에는 같은 선상에 있는 것이 짝지어지고 남는거는 무시가된다.
function a(w, x, y){
console.log(w, x, y);
}
a('hello', 'parameter', 'argument', '추가')
이렇게 기능 자체(함수)는 미리 만들어 두고 선언할 때 어떤 값이 들어갈지 모르기에 실행(호출)하였을 때 값이 들어오는 것이다. 예제로 화살표 함수를 이용해서 만들게되면
const arrowPlus = (x, y, z) => {
return x * y * z;
}
arrowPlus(2, 3, 5);
//중괄호와 return이 이어지면 생략이 가능하다.
const arrowPlus = (x, y, z) => x * y * z;
arrowPlus(2, 3, 5);
//그리고 알아보기 쉽게 괄호로 묶을 수 있다.
const arrowPlus = (x, y, z) => (x * y * z);
arrowPlus(2, 3, 5);
이렇게 표현이 된다. 화살표 함수의 특징은 중괄호와return
이 바로 이어지면 생략이 가능하다.
//나의 정보를 변수로 선언하면 이렇게 표현이 가능하다.
const name = '이채원';
const year = 1992;
const gender = 'male';
const month = 9;
const date = 21;
/*이렇게 각각 변수를 활용하여 표현하였다 하지만 여기서 공통적인 집합이 있는데 이것은 나를
표현하고 있다는 것이다. 이것을 따로 변수로 표현하는게 아닌 묶을 수 있는데 배열처럼 묶을 수 있다.
이것을 객체 리터널로 묶을 수 있다.*/
const chaewon = { //객체 리터널
// 총 5개의 속성
name : '이채원', //속성의 이름 : 속성 값
year : 1992,
gender : 'male',
month : 9,
date : 21,
};
//이렇게 표현할 수 있다 이것이 객체 리터널이다.
배열을 대신해서 왜 객체 리터널을 사용하는 이유는 각 값에 이름이 필요할 때 사용한다.
중괄호를객체 리터널
그 안에 있는 것들을속성
이라 하며 그 속성의 왼쪽은속성의 이름
오른쪽은속성의 값
이다.속성의 이름
에는 따옴표를 붙여야하는 경우가 있는데const test ={ a : 'good', '2a' : 'bad', '2 a' : 'bad', '2-a' : 'bad', }
이렇게 앞에 숫자, 띄어쓰기, 특수문자의 경우에는 따옴표를 표시해줘야 한다.
속성의 내부에 접근하는 방식은 아래와 같다.
const test ={ a : 'good', '2a' : 'bad', '2 a' : 'bad', '2-a' : 'bad', } //객체 리터널 속성에 접근하는 방식 console.log(test.a); console.log(test['a']);
여기서 중요한 부분은 대괄호를 사용할때는 꼭 따옴표로 사용해야한다. 문자열이기 때문이다. 이유는 앞서 말했던 앞에 숫자, 띄어쓰기, 특수문자는
test.a
로 표현할 수 없기에 대괄호를 이용한test['a']
를 사용해야한다.console.log(test['2a']); console.log(test['2 a']); console.log(test['2-a']);
그리고 대괄호에서 따옴표를 빼먹게 되면 문자열이 아닌 변수가된다. 그리고 없는
속성
에 접근하게되면undefined
가 뜬다.
객체 리터널에 추가 또는 수정은 배열과 똑같다.
const chaewon = { name : 'name', year : 1992, month : 9, date : 21, } chaewon.name = 'chaewon' //속성 값을 변경하는 방법 chaewon.country = '경기도' // 속성을 추가하는 방법
객체의 속성 또한 제거할 수 있다.
const chaewon = { name : 'name', year : 1992, month : 9, date : 21, } delete chaewon.date console.log(chaewon.date);
const
는 상수지만 배열과 같이 객체는 변경할 수 없지만 내부는 변경이 가능하다.
const debug = {
log : function(value){
console.log(value);
},
}
debug.log('hello, Method')
객체의 모양이 같다고 비교했을 때
true
는 나오지 않는다.false
가 나온다.
true
가 나오려면 변수안에 저장을하여 비교를 해야한다. 이유는 객체를 만드는 순간 새로운 객체를 만든 거기 때문에
새로운 객체와 새로운 객체는 당연 비교했을 때 다르다고 나온다
const a = {
name : 'chaewon',
}; //객체 리터널
const array = [1, 2, a]; //배열 리터널
console.log(a === array[2]);
이렇게 비교했을 때 같다고 표시된다. 위에 말했던 내용(false
가 나오는 이유)처럼 배열 또한 객체와 똑같다. 예를 들어보자
const a = { name : 'chaewon',};
const array = [1, 2, a]; //여기서 배열을 한 번 만들었고
console.log( array === [1, 2, a]); // 여기서 비교했을 오른쪽에 있는 배열을 또 새로 만든 것이다.
//과연 결과값이 어떻게 나올까?
false
가 나온다. 똑같은 배열인데false
가 나오는 이유는 배열을 2번 새로만들었기 때문이다.
첫번째 변수에 저장했을 때 1번 밑에 비교했을 때 2번 이렇게 2개의 변수가 만들어 진거다.
메모리 관점에서 본다면
결국 array 변수로 저장한 것과 따로 저장하지 않은 것은 따로 저장되어 있기에 같을 수 없다. a의 경우에는 당연 변수로 선언하여
만들었고 가르키고 있기에 array에 들어있는게 맞다.
객체 또는 배열 아닌 값은 객체인 경우에는 변수에는 주소가 저장되어 있고 일반 값인 경우에는 그 값이 그냥 저장되어 있다.
객체 또는 배열 아닌 값을원시값
이라고 한다.
이렇게 배열 또는 객체가 아닌원시값
들은 따로 저장되어 있는 곳이 있기에 비교를 하더라도true
가 나올 수 있는 것이다.
쉽게 말해서 객체 또는 배열 끼리는 변수에 넣어두지 않으면 모양이 같게 생겨도 다르고 원시값은 모양이 똑같으면 똑같다고 생각하면 된다.
이런 객체의 특성(?)으로 인해 객체를 사용할 때 반드시 알아야 하는 개념은 바로
참조(reference)
이다.const a = { name : 'chaewon'}; //객체를 변수에 넣어주고 const b = a; //b에 a를 대입한다. a.name = 'who'; //여기서 객체 안에 있는 name을 변경하게되면 console.log(b.name); //당연 who가 나오게된다.
이렇게 a와 b가 같은 객체를참조
하고 있다고 표현한다.
원시값은 객체와 다르다.let a = 'chaewon'; let b = a; a = 'who'; console.log(b);
이렇게 b는 a와 같이 변경되는 것이 아니라 기존에 저장된 값이 나오게 된다. 그림과 같이 메모리의 별도 공간에서 추가되기에
변경된다고 객체처럼 같이 변경되지 않는다.객체의 공간과 객체가 아닌 것들의 공간은 다르다.