코드잇 Codeit/Front-End

코드잇 javaScript 기초 - 프로그래밍과 데이터 in JavaScript ③ 자료형 심화

꼽파 2023. 5. 4. 23:22



다양한 숫자 표기법

// 숫자 표기법
let millionaire = 1000000000; // 십억
let myNumber = 1e9; // 지수표기법 ---- 10의 9제곱 = 십억

console.log(millionaire); // 1000000000
console.log(myNumber); // 1000000000
console.log(millionaire === myNumber); // true

// 지수표기법 활용
console.log(25e5 === 2500000);
console.log(5.3e3 === 5300);
console.log(-6.1e8 === -610000000);

console.log(16e-5 === 0.00016);
console.log(3.5e-3 === 0.0035);
console.log(-9.1e-5 === -0.000091);
// 왼쪽 숫자가 음수면 십의 거듭제곱만큼 나눈다

// 숫자 표기법

// 16진법 (Hexadecimal)
// 0x에 16진수 쓰기
let hex1 = 0xff; // 255
let hex2 = 0xFF; // 255

// 8진법 (Octal)
// 0o에 8진수 쓰기
let octal = 0o377; // 255

// 2진법 (binary numeral system)
// 0b에 이진수 쓰기
let binary = 0b11111111; // 255

console.log(hex1);  // 255
console.log(hex2);  // 255
console.log(octal); // 255
console.log(binary);// 255

// 콘솔에 출력될 때는 10진수로 출력됨


숫자형 메소드

// Number

let myNumber = 0.3591;

// toFixed(0 ~ 100)
console.log(myNumber.toFixed(3)); // 0.359
// 소수점 아래 자리수를 고정해줌

console.log(myNumber.toFixed(7)); // 0.3591000
// 소수점 아래 자리수가 부족하면 0으로 대체됨

// 주의할 점 : 계산된 값이 문자열임
console.log(typeof myNumber.toFixed(7)); // string
// 더하기 같은 연산할 때 문자열 연결이 될 수 있으므로 주의
// ---> Number 함수로 숫자형으로 형변환 해줘야 함
 
// 숫자형으로 형변환
console.log(Number(myNumber.toFixed(7))); // 0.3591
console.log(typeof Number(myNumber.toFixed(7))); // number

자바스크립트에서는 어떤 값 앞에 더하기 기호를 붙여주면 Number함수와 똑같은 결과를 얻을 수 있음.

// Number

let myNumber = 0.3591;

// toFixed(0 ~ 100)
console.log(+myNumber.toFixed(2)); // 0.36
// 해당 숫자가 문자 -> 숫자로 형변환됨
console.log(typeof +myNumber.toFixed(2)); // number

toString

// Number
let myNumber = 255;

// toString(2 ~ 36)
console.log(myNumber.toString(2)); // 11111111
// 2진수로 변환
console.log(myNumber.toString(8)); // 377
// 8진수로 변환
console.log(myNumber.toString(16)); // ff
// 16진수로 변환

// 메소드 이름대로 결과값도 문자형임

정수에 toString 매소드를 직접 사용하는 방법

- 정수 옆에 소수점 2개를 붙이기 ex. 255..toString(2)

- 양옆을 소괄호로 감싸주기 ex. (255).toString(2)

// Number
let myNumber = 255;

// toString(2 ~ 36)
console.log(255.toString(2)); // error
// 정수에 소수점을 붙이면 에러가 뜸
// -> 이게 소수점인지 메소드 사용하려고 찍은 점인지 알 수 없어서

// ♥ 정수에 소수점 2개 붙이기
console.log(255..toString(2)); // 11111111
// 숫자에 바로 메소드를 사용할 수 있음

// ♥ 양옆을 소괄호로 감싸줌
console.log((255).toString(2));  // 11111111
let myNumber = 2.37e-2

/*
지수표기법 : 알파벳 e를 활용해서 표기하는 방식
알파벳 'e'의 왼쪽에 있는 숫자에 오른쪽에 있는 수만큼 10의 거듭제곱하기

알파벳 e의 오른쪽 값이 음수
→ 이 숫자만큼 10의 거듭제곱으로 나누는 의미

0.0237
*/

console.log(myNumber.toFixed(2));

/*
해당 숫자를 초과하는 자릿수일 경우 : 바로 직후의 자릿수가 반올림

0.0237 ---> 0.02 or 0.03으로 표기됨
3이 5보다 작으므로 반올림하면 0.02
*/

// 0.02
// "숫자" 123을 표현하는 것이 아닌 것은?

// 1.
Number((4 * 30 + 3).toString(10));
/*
(4 * 30 + 3).toString(10)에서
문자열 123이 나옴.
Number(123)이므로 결국 숫자 123이 됨.
*/

// 2.
(123.456).toFixed(0);
/*
123.456을 소수점 0자리 (소수점 없애고 정수로) 표현
4는 5보다 작으므로 소수점 첫번째 자리를 반올림하여
문자 123이 출력됨.
*/
// ** toFixed, toString --> 결괏값이 "문자열"로 리턴됨

// 3.
1.23e2;
/*
1.23에 10의 제곱을 곱하면
숫자 123
*/

// 4.
0x7b.toString(10) * 1;
/*
0x => 16진수
7b를 16진수로 변환하면
7은 16^1 자리, b는 16^0자리
7 x 16 + 11 = 123

참고) 16진수는 0~9 / a~F (10~15)
*/

Math 객체

// 절댓값 (Absolute Number)
// Math.abs(x)
console.log(Math.abs(-10)); // 10
console.log(Math.abs(10)); // 10

// 최댓값 (Maximum)
// Math.max() --> 여러 수 중 가장 큰 값이 리턴됨.
console.log(Math.max(2, -1, 4, 5, 0));
// 5

// 최솟값 (Minimum)
// Math.min() --> 여러 수 중 가장 작은 값이 리턴됨.
console.log(Math.min(2, -1, 4, 5, 0));
// -1

// 거듭제곱 (Exponentiation)
// Math.pow(x, y) --> x의 y승
console.log(Math.pow(2, 3)); // 8
console.log(Math.pow(5, 2)); // 25

// 제곱근 (Square Root)
// Math.sqrt(x) --> x의 제곱근
console.log(Math.sqrt(25)); // 5
console.log(Math.sqrt(49)); // 7

// 반올림 (Round)
// Math.round(x) --> x의 반올림한 값
console.log(Math.round(2.3)); // 2
console.log(Math.round(2.4)); // 2
console.log(Math.round(2.49)); // 2
console.log(Math.round(2.5)); // 3
console.log(Math.round(2.6)); // 3

// 버림과 올림 (Floor and Ceil)
// Math.floor(x) --> x의 버림 값
// Math.ceil(x) --> x의 올림 값
console.log(Math.floor(2.4)); // 2
console.log(Math.floor(2.49)); // 2
console.log(Math.floor(2.8)); // 2
console.log(Math.ceil(2.4)); // 3
console.log(Math.ceil(2.49)); // 3
console.log(Math.ceil(2.8)); // 3

// 난수 (Random)
// Math.random --> 0이상 1미만 값이 랜덤으로 리턴됨.
// 15~16자리까지 나옴.
console.log(Math.random()); // 0.4587968329021128
console.log(Math.random()); // 0.9011835243246293
console.log(Math.random()); // 0.4542019253251022
console.log(Math.random()); // 0.7536305571425335

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math

 

Math - JavaScript | MDN

Math 는 수학적인 상수와 함수를 위한 속성과 메서드를 가진 내장 객체입니다. 함수 객체가 아닙니다.

developer.mozilla.org


let sum = 0.1 + 0.2;

console.log(sum);

// 0.30000000000000004
/*
자바스크립트 뿐만 아니라 파이썬, 루비, 자바 등에서도 똑같이 나타남.
*/

일반적으로 사용하는 십진수를 컴퓨터가 이진수로 변환하기 때문에 발생하는 현상임.

이진수로 변환하였을 때 무한소수가 되는 경우는 특정 자리에서 반올림함.

이러한 문제를 해결하는 방법이 있음.

// 방법 1. toFixed 메소드 사용

let sum1 = 0.1 + 0.2;

console.log(sum1.toFixed(1));
// 소수 첫번째 자리수까지 나타내도록 함
// toFixed 메소드의 결과는 문자열임 -> 숫자로 형변환 필요함.

console.log(+sum1.toFixed(1));
console.log(Number(sum1.toFixed(1)));

// 방법 2. Math.round 메소드 사용

let sum2 = 0.1 + 0.2;

console.log(Math.round(sum2 * 10) / 10);
// sum을 정수로 만들고 -> 반올림 -> 다시 10으로 나눔

// 오차를 완벽히 방지하는 방법은 없음

문자열 심화

// String
let myString = 'Hi Codeit';

// ▶ 문자열 길이
// length 프로퍼티
console.log(myString.length); // 9
// 공백 포함

// ▶ 요소 접근
// 문자열의 각 문자에 접근하는 방법
// 공백 포함

 // 대괄호 표기법
console.log(myString[3]); // C
// charAt 메소드
console.log(myString.charAt(3)); // C

// ▶ 요소 탐색
console.log(myString.indexOf('a')); // -1
// 앞부터 찾으면 없음
console.log(myString.indexOf('i')); // -1
// 앞부터 찾으면 1번 인덱스에 있음
console.log(myString.lastIndexOf('i')) // 7
// 뒤부터 찾으면 7번 인덱스에 있음

// ▶ 대소문자 변환
// 대문자 toUpperCase
console.log(myString.toUpperCase()); //HI CODEIT
// 소문자 toLowerCase
console.log(myString.toLowerCase()); //hi codeit

// ▶ 양 끝 공백 제거
// trim 메소드

let ourString = '  Hi Codeit  ◆ ';
let yourString = '  Hi Codeit  ◆ ';

console.log(ourString); //   Hi Codeit  ◆ (공백 O)
console.log(yourString.trim()); // Hi Codeit  ◆ (공백 X)

// ▶ 부분 문자열 접근 slice(start, end)
console.log(myString.slice(0, 2)); // Hi
// 0번 인덱스부터 2번 인덱스 직전까지 (0번부터 1번까지 문자열)
console.log(myString.slice(3)); // Codeit
// 3번 인덱스부터 끝까지
console.log(myString.slice()); // Hi Codeit
// 문자열 전체를 리턴함
// 문자열과 배열의 비슷한 점과 다른 점

/*
♣♣♣ 비슷한 점
length 프로퍼티, 대괄호 표기법으로 접근 등
*/

// for-of문으로 문자열 myString의 각 요소에 접근하여 출력

let myString = 'Codeit';

for (let str of myString) {
    console.log(str);
}

/*
출력결과 :
C
o
d
e
i
t
*/
/*
♣♣♣ 다른 점
비슷하긴 하지만 완전히 같을 순 없음
*/

// 1. 자료형

let myString = 'Codeit';
let myArray = ['C', 'o', 'd', 'e', 'i', 't'];

console.log(typeof myString); // string
console.log(typeof myArray); // object

console.log(myString === myArray); // false
console.log(myString == myArray); // false

// 2. mutable(바뀔 수 있는) vs immutable(바뀔 수 없는)

// 배열은 mutable
let UrArray = ['C', 'o', 'd', 'e', 'i', 't'];
UrArray[0] = 'B'; // UrArray의 0번 인덱스 원소를 B로 바꿈
console.log(UrArray);
// ['B', 'o', 'd', 'e', 'i', 't']
 
// 문자열은 immutable
let UrString = 'Codeit';
UrString[0] = 'B';
console.log(UrString);
// Codeit
// 문자열이 가진 메소드들은 모두 return 값들을 활용하고, 본래의 문자열 값을 수정하지 않음.

가사(문자열)의 일부분만 떼어내기

lyrics 문자열에 적절한 메소드를 활용해서 형돈의 부분만 떼어내고 hyungdon 변수에 재할당하기

let lyrics = "[재석]너에게 나 하고 싶었던 말 고마워 미안해 함께 있어서 할 수 있어서 웃을 수 있어[준하] 정말 고마웠어 내 손을 놓지 않아줘서 힘을 내볼게 함께 있다면 두렵지 않아[홍철] 내가 늘 웃으니까 내가 우습나 봐 하지만 웃을 거야 날 보고 웃는 너 좋아[명수] 자꾸만 도망치고 싶은데 저 화려한 큰 무대 위에 설 수 있을까? 자신 없어..[하하] 지금까지 걸어온 이 길을 의심하지는 마 잘못 든 길이 때론 지도를 만들었잖아[형돈] 혼자 걷는 이 길이 막막하겠지만 느리게 걷는 거야 천천히 도착해도 돼[길] 술 한 잔 하자는 친구의 말도 의미 없는 인사처럼 슬프게 들릴 때 날 찾아와";

let hyungdon = null;

startIndex = lyrics.indexOf('[형돈]');
// 형돈 파트 시작 부분
lastIndex = lyrics.indexOf('[길]')
// 형돈 파트 끝 부분 (길 시작 직전까지)

hyungdon = lyrics.slice(startIndex, lastIndex)
// 주의할 점은 slice(start, end)에서 end의 직전까지 출력함.
// ex. slice(200, 300)이면 인덱스 200에서 299까지 출력되는 것임.
// -> indexOf에서 '[길]'을 입력해야 그 직전까지 출력되는 것임.

console.log(hyungdon)

// [형돈] 혼자 걷는 이 길이 막막하겠지만 느리게 걷는 거야 천천히 도착해도 돼
// 멤버별 파트를 한 줄씩 띄워서 씀
let lyrics =
"[재석]너에게 나 하고 싶었던 말 고마워 미안해 함께 있어서 할 수 있어서 웃을 수 있어\n" +
"[준하] 정말 고마웠어 내 손을 놓지 않아줘서 힘을 내볼게 함께 있다면 두렵지 않아\n" +
"[홍철] 내가 늘 웃으니까 내가 우습나 봐 하지만 웃을 거야 날 보고 웃는 너 좋아\n" +
"[명수] 자꾸만 도망치고 싶은데 저 화려한 큰 무대 위에 설 수 있을까? 자신 없어..\n" +
"[하하] 지금까지 걸어온 이 길을 의심하지는 마 잘못 든 길이 때론 지도를 만들었잖아\n" +
"[형돈] 혼자 걷는 이 길이 막막하겠지만 느리게 걷는 거야 천천히 도착해도 돼\n" +
"[길] 술 한 잔 하자는 친구의 말도 의미 없는 인사처럼 슬프게 들릴 때 날 찾아와\n";

// 객체로 만들어서 응용해 봄
// 멤버 입력을 입력하면 그에 맞는 가사를 출력하는 것임.
 
let Moodo = {
    '재석': '너에게 나 하고 싶었던 말 고마워 미안해 함께 있어서 할 수 있어서 웃을 수 있어',
    '준하': '정말 고마웠어 내 손을 놓지 않아줘서 힘을 내볼게 함께 있다면 두렵지 않아',
    '홍철': '내가 늘 웃으니까 내가 우습나 봐 하지만 웃을 거야 날 보고 웃는 너 좋아',
    '명수': '자꾸만 도망치고 싶은데 저 화려한 큰 무대 위에 설 수 있을까? 자신 없어..',
    '하하': '지금까지 걸어온 이 길을 의심하지는 마 잘못 든 길이 때론 지도를 만들었잖아',
    '형돈': '혼자 걷는 이 길이 막막하겠지만 느리게 걷는 거야 천천히 도착해도 돼',
    '길': '술 한 잔 하자는 친구의 말도 의미 없는 인사처럼 슬프게 들릴 때 날 찾아와'
}

function printLyrics(member) {
    if ( member in Moodo ) {
        return Moodo[member];
        // Moodo 객체의 member 프로퍼티에 해당하는 값을 반환
        // 주의 : Moodo['member']은 member라는 프로퍼티 이름이 있어야 함.
        //       (재석, 준하, 홍철, member 이런식으로)
    } else {
        return "다시 입력해주세요.";
        // 여기서 return을 써야 Line 33에서 undefined가 출력되지 않음.
    }
}

console.log(printLyrics('형돈'))
console.log(printLyrics('코드잇'))

기본형과 참조형

 

기본형(Primitive Type) : Number, String, Boolean, Null, Undefined (변수=값)

참조형(Reference Type) : Object (변수=주소값)

/*
변수에 기본형 값을 할당하면
해당 변수 이름을 가진 상자에 그 값을 넣어주는 것과 같음
*/

let x = 3;
let y = x; // y는 x가 갖고 있는 3이 들어감

console.log(x); // 3
console.log(y); // 3
y = 5; // y가 갖고 있는 값은 3이 아니라 5
console.log(x); // 3
console.log(y); // 5
/*
변수에 기본형 값을 할당하면
해당 변수 이름을 가진 상자에 그 값을 넣어주는 것과 같음
*/

let x = {name: 'Codeit'};  
let y = x; // y에 {name: 'Codeit'};이 할당됨

console.log(x); // {name: 'Codeit'}
console.log(y); // {name: 'Codeit'}
y.birth = 2017; // 객체 y에 새로운 프로퍼티를 생성함

console.log(x); // {name: 'Codeit', birth: 2017} ---> 왜??!??!?!?!??!
console.log(y);// {name: 'Codeit', birth: 2017}

JavaScript에서 객체는 참조(reference) 형식으로 할당됨.
y = x와 같이 객체를 변수에 할당할 때는 실제로는 객체의 값이 아닌, 메모리상에서 객체를 참조하는 주소(reference)가 변수에 할당됨.
y.birth = 2017과 같이 y 객체에 새로운 프로퍼티를 추가하는 경우 :

- x 변수가 참조하는 객체와 y 변수가 참조하는 객체가 동일함.

- x 변수를 출력해도 동일한 객체가 출력되며, x 변수에도 새로운 프로퍼티가 추가되어 있는 것임.

// 배열의 경우

let x = [1, 2, 3];
let y = x;

console.log(x); // [1, 2, 3]
console.log(y); // [1, 2, 3]
y[2] = 4; // y의 세번째 원소를 4로 수정
console.log(x); // [1, 2, 4]
console.log(y); // [1, 2, 4]

// 배열도 마찬가지로 변수 X에 주소값이 할당되므로
// X변수가 참조하는 객체와 Y변수가 참조하는 객체가 같음
let x = {
    numbers: [1, 2, 3, 4],
    title: 'Codeit',
  };
  /*
  2개의 프로퍼티를 가진 객체가 변수 x에 할당됨
  객체는 참조형 값
  --> 변수 x에 주소값이 저장됨
  */

  let y = x.numbers;
  // numbers 프로퍼티 값이 배열(참조형)
  // --> 배열의 주소값이 y에 할당됨
  let z = x.title;
  // title 프로퍼티 값이 문자열(기본형)
  // --> 변수 z에 문자열 값이 그대로 복사됨.
  // --> x.title과 z는 독립적인 변수!!!!

 /* x.numbers를 변경하면 y가 변경되나,
    x.title을 변경해도 z는 변경되지 않음. */

  x.numbers.unshift(5);
  // x.numbers에 배열의 첫요소로 5를 넣음
  // -> y에도 5가 추가됨
  x.title = 'Hello';
  // 객체 x의 title 값이 'Hello'로 바뀜
  // -> z는 변함없이 'Codeit'을 유지함
 
  console.log(y); // [5, 1, 2, 3, 4]
  console.log(z); // Codeit

참조형 복사하기

// 참조형 복사하기 (Reference Type Copy)

let numbers1 = [1, 2, 3];
let numbers2 = numbers1;

numbers2.push(4);
// [1, 2, 3, 4]

console.log(numbers1);
console.log(numbers2);
// [1, 2, 3, 4]

/*
상황에 따라서는 참조형 값을 그대로 복사하고 싶을 수 있음
number2만 변경하고 싶을 때
---> slice를 활용함
*/
// 참조형 복사하기 (Reference Type Copy)

let numbers1 = [1, 2, 3];
let numbers2 = numbers1.slice();
// 배열을 복사하는 것 같은 효과가 있음

numbers2.push(4);
// [1, 2, 3, 4]

console.log(numbers1);
// [1, 2, 3]
console.log(numbers2);
// [1, 2, 3, 4]

// 참조형 복사하기 (Reference Type Copy)
// 배열의 경우

let course1 = {
    title: '파이썬 프로그래밍 기초',
    language: 'Python'
};

let course2 = course1;

course2.title = '알고리즘의 정석';

console.log(course1);
console.log(course2);
// {title: '알고리즘의 정석', language: 'Python'}

// 객체에는 slice 메소드가 없음
// --> Object.assign({}, course1)

Object.assign(target, sources) 활용하기

// 참조형 복사하기 (Reference Type Copy)
// 배열의 경우

/*
Object.assign(target, sources)
"target 객체에" 하나 이상의 소스 객체의
모든 열거 가능한 프로퍼티를 "복사"하는데 사용

target : 복사될 대상 객체
sources : 복사할 소스 객체
*/

let course1 = {
    title: '파이썬 프로그래밍 기초',
    language: 'Python'
};

let course2 = Object.assign({}, course1);
// 빈 객체 {}에 course1 객체의 프로퍼티를 복사하여
// course2 객체를 생성하는 코드

course2.title = '알고리즘의 정석';
// course1의 객체는 변경되지 않는다

console.log(course1);
// {title: '파이썬 프로그래밍 기초', language: 'Python'}
console.log(course2);
// {title: '알고리즘의 정석', language: 'Python'}
// 참조형 복사하기 (Reference Type Copy)
// 객체체의 경우

// for-in문 활용하기

let course1 = {
    title: '파이썬 프로그래밍 기초',
    language: 'Python'
};

let course2 = {};

for (let key in course1) {
    course2[key] = course1[key];
}
// course1의 원소를 course2에 하나씩 넣어준다
// --> 서로 독립적인 변수

course2.title = '알고리즘의 정석';
// course2만 변경됨

console.log(course1);
// {title: '파이썬 프로그래밍 기초', language: 'Python'}
console.log(course2);
// {title: '알고리즘의 정석', language: 'Python'}

for-in문은 course1과 course2에만 해당되어 한정적으로만 사용됨.

→ course3, course4가 생긴다면 어떻게 할까? (함수 활용)

// 참조형 복사하기 (Reference Type Copy)
// 객체의 경우

// for-in문 활용한 "함수"

function cloneO(object) {
    let temp = {} // 빈 객체를 temp에 할당

    for (let key in object) {
        temp[key] = object[key]; //object의 원소를 하나씩 temp에 할당
    }
    return temp;
}

let course1 = {
    title: '파이썬 프로그래밍 기초',
    language: 'Python'
};

let course2 = cloneO(course1);
// cloneO 함수를 통해 course1의 프로퍼티가 course2에 복사됨.

course2.title = '자료구조';
// course2만 변경됨

console.log(course1);
// {title: '파이썬 프로그래밍 기초', language: 'Python'}
console.log(course2);
// {title: '자료구조', language: 'Python'}
// 참조형 복사하기 (Reference Type Copy)

// for-in문 활용한 "함수"

function cloneO(object) {
    let temp = {}

    for (let key in object) {
        temp[key] = object[key];
    }
    return temp;
}

// course1에 prerequisite(선수과목) 추가
let course1 = {
    title: '파이썬 프로그래밍 기초',
    language: 'Python',
    prerequisite: [] // 배열
};

let course2 = cloneO(course1);

course2.title = '자료구조';
course2.prerequisite.push('파이썬 프로그래밍 기초');

console.log(course1);
// {title: '파이썬 프로그래밍 기초', language: 'Python', prerequisite: Array(1)}
console.log(course2);
// {title: '자료구조', language: 'Python', prerequisite: Array(1)}

// course2의 배열에 넣었는데, course1에 복사됨!!!

// 참조형 복사하기 (Reference Type Copy)

function cloneO(object) {
   if (object === null || typeof object !== 'object') {
     return object;
   } // object가 객체가 아니거나 null이면
     // object를 반환함

   let temp;
   if (Array.isArray(object)) {
    temp = [] // object가 배열인 경우 temp에 빈 배열 할당
   } else {
    temp = {}; // object가 배열이 아니면 temp에 빈 객체를 만듦
   }
 
   for (let key of Object.keys(object)) {
    temp[key] = cloneObject(object[key])
   } // object의 모든 키를 배열로 가져옴
     // object의 각 키에 대해 반복 -> 재귀적으로 cloneO함수 호출
   return temp;
}  // 복사된 객체의 각 키와 값이 temp 객체에 저장되고
   // 최종적으로 temp 객체가 리턴됨

let course2 = cloneO(course1);

course2.title = '자료구조';
course2.prerequisite.push('파이썬 프로그래밍 기초');

console.log(course1);
console.log(course2);

레시피 만들기

// 배열을 복사하는 함수 baristar를 생성함
function baristar(array) {
    let temp = [] // 빈 배열 temp를 하나 생성
    temp = array.slice()  // temp에 array의 원소를 넣어줌
    return temp;  // array의 원소만 복사된 temp를 반함
// 함수 마지막에 return문 빼먹지 말기
  }
 
  let espresso = ['espresso'];
 
  let americano = baristar(espresso);
  americano.push('water');
 
  let caffeLatte = baristar(espresso);
  caffeLatte.push('milk');
 
  let caffeMocha = baristar(caffeLatte);
  caffeMocha.push('chocolateSyrup')
 
  let vanillaLatte = baristar(caffeLatte);
  vanillaLatte.push('vanillaSyrup')
 
// 다 독립적으로 복사가 되기 때문에 원소 추가해도 서로 영향 X
 
  // 테스트 코드
  console.log(espresso);
  console.log(americano);
  console.log(caffeLatte);
  console.log(caffeMocha);
  console.log(vanillaLatte);
 
  // 실행결과
[ 'espresso' ]
[ 'espresso', 'water' ]
[ 'espresso', 'milk' ]
[ 'espresso', 'milk', 'chocolateSyrup' ]
[ 'espresso', 'milk', 'vanillaSyrup' ]  

const를 변수로 사용하기

// 변수는 const로 선언하세요?
// const와 let의 차이점 : 재할당 여부

let x = 1;
console.log(x);
x = 2;
console.log(x);

const y = 3;
console.log(y);
y = 4; // 새 값을 할당하려고 하면 오류가 남
console.log(y);

변수는 코드가 쓰이는 순간에 상수로 동작하는 경우가 많음.

let x = 3;
let y = x + 2;

console.log(x);
console.log(y);

x = 4;
console.log(x);

y = x * y;
console.log(y);

// 코드가 짧으면 상관이 없는데 길이가 길어지면 혼란스러울 수 있음
// 언제 바뀔지 모르니까 const로 변수를 선언함
// 그럼 const가 변수일 때와 상수일 때는 어떻게 구분하냐?

변수(variable) : myName

상수(constant) : MY_NAME

const x = {name: 'Codeit'}; // 객체
x.birth = 2017; // 객체 x의 프로퍼티를 생성

const 키워드로 선언된 객체 x에 새로운 프로퍼티를 생성함.

const 키워드로 변수를 선언해도 변수의 값이 충분히 변할 수 있음.

let team1 = ['Drum', 'Bass', 'Saxophone'];
const team2 = team1;
// ['Drum', 'Bass', 'Saxophone'];
// 배열은 참조형 값이라 주소 값이 복사됨
// --> team1과 team2는 서로 같은 배열을 가리키게 됨.

team1.splice(2, 1, 'Trumpet');
// ['Drum', 'Bass', 'Trumpet'];
// team1과 team2가 모두 바뀜

team2.splice(2, 1, 'Piano');
// ['Drum', 'Bass', 'Piano'];
// team1과 team2가 모두 바뀜

console.log(team1);
console.log(team2);
// ['Drum', 'Bass', 'Piano'];

/*
team1과 team2는 같은 배열을 참조하고 있으므로,
하나의 배열을 수정하면 다른 배열도 동일하게 수정됨
*/

 


변수 var을 사용하지 않는 이유

// 변수 선언

var myVariable;
myVariable = 'codeit';

// ♠  중복 선언 허용

var myVariable = 'codeit';
console.log(myVariable);
var myVariable = 'Codeit!';
console.log(myVariable);
// --> 기존 변수를 덮어 쓰는 것(O), 재할당 (X)

// 함수 스코프
/* var 키워드로 선언한 변수는
scope가 function에서만 구분되어 있음. */

{
    let x = 10;
  }
 
  function myFunction() {
    let y = 90;
  }
 
  console.log(x);
// Uncaught ReferenceError: x is not defined
  console.log(y);
// 90

 {
    var x = 3;
  }
 
  function myFunction() {
    var y = 4;
  }
 
  console.log(x);
// 3
  console.log(y);
// Uncaught ReferenceError: y is not defined
// 지역변수 구분이 함수에만 있어서 x는 전역변수처럼 쓰임
// 끌어올림 (Hoisting)

// 변수에서

console.log(myVariable); // error
let myVariable;

/*
→ Uncaught ReferenceError: Cannot access 'myVariable' before initialization
let과 const로 선언한 변수는 선언되기 전에 사용할 수 없음.
*/

console.log(UrVariable); // undefined
var UrVariable;

/*
→ undefined
호이스팅(hoisting) : 변수가 끌어올려 지는 현상
선언과 동시에 값을 할당하더라도,
선언문만 올려지기 때문에 값은 그대로 두 번째 줄에 남아있음.
*/

console.log(myVariable); // undefined
var myVariable = 2;
console.log(myVariable); // 2

// 함수에서

sayHi();

function sayHi() {
  console.log('hi'); // hi
}

/*
함수를 한 번 선언하면 유연하게 쓸 수 있으나,
코드의 흐름을 방해함.
*/

 

728x90