JavaScript (6)

깨진알·2023년 12월 5일

JavaScript

목록 보기
6/21

JavaScript 자료형 심화

1. 숫자 표기법

// 지수 표기법
let myNumber = 1e9; // 10억, 왼편의 수에 오른쪾의 수만큼 10의 거듭제곱을 해준다
let myNumber2 = 3.5e-3; // 0.0035, 음수일 경우 오른쪽 자리수 만큼 나누어 주면 된다

// 16진법 (Hexadecimal)
let hex1 = 0xff; // 255
let hex2 = 0xFF; // 255

// 8진법 (Octal)
let octal = 0o377; // 255

// 2진법 (Binary Numeral System)
let binary = 0b11111111; // 255

2. 숫자형 메소드

let myNumber = 0.3591;

// toFixed(0 ~ 100)
console.log(myNumber.toFixed(3)); // 0.359, 소수점 4자리의 수를 반올림하여 소수점 3자리까지 표기
console.log(myNumber.toFixed(2)); // 0.36 (String)

// 결과값은 문자열으로 나온다 -> 숫자형으로 사용하고 싶으면 Number() 사용
console.log(Number(myNumber.toFixed(2))); // 0.36 (Number)
console.log(+myNumber.toFixed(2)); // 0.36 (Number)

// toString(2 ~ 36) -> 해당 진법으로 변환해준다 -> 결과값도 마찬가지로 문자열이다
console.log(myNumber, toString(2)); // 11111111
console.log(myNumber, toString(8)); // 377
console.log(myNumber, toString(16)); // ff

console.log(255..toString(2)); // 11111111, 정수를 바로 사용할 때는 ..을 입력해주어야 한다
console.log((255).toString(8)); // 377, 괄호를 사용해주어도 된다

3. Math 객체

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

// 최댓값
console.log(Math.max(2, -1, 4, 5, 0)); // 5

// 최솟값
console.log(Math.min(2, -1, 4, 5, 0)); // -1

// 거듭제곱
console.log(Math.pow(2, 3)); // 8
console.log(Math.pow(5, 2)); // 25

// 제곱근
console.log(Math.sqrt(25)); // 5
console.log(Math.sqrt(49)); // 7

// 반올림
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

// 버림과 올림
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

// 난수
console.log(Math.random()); // (0 이상 1 미만의 값) 0.214637453

4. 문자열 심화

let myString = 'Hi Cracked_Egg';

// 문자열 길이
console.log(myString.length); // 14, length 프로퍼티

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

// 요소 탐색
console.log(myString.indexOf('g')); // 12
console.log(muString.lastIndexOf('g')); // 13

// 부분 문장열 접근 slice(start, end) -> end 인덱스 바로 직전까지 가져온다
console.log(myString.slice(0, 2)); // Hi
console.log(myString.slice(3)); // Cracked_Egg, 시작지점부터 끝까지 return
console.log(myString.slice()); // Hi Cracked_Egg, 모두 생략하면 문자열 전체를 return

// 양 끝 공백 제거
console.log(myString.trim()); // Hi Cracked_Egg, trim 메소드(양 쪽에 공백이 있을 경우)

// 대소문자 변환
console.log(myString.toUpperCase()); // HI CRACKED_EGG, 대문자
console.log(myString.toLowerCaSE()); // hi cracked_egg, 소문자

5. 문자열과 배열

  • 비슷한 점

실제로 배열과 문자여래 모두 length 프로퍼티를 가지고 있고, 대괄호 표기법으로 각 요소에 접근할 수 있다. 꽤 많은 메소드들이 배열과 문자열 모두 동일하게 사용되고 있으며, for..of문을 문자열에 활용할 수도 있다.

let myString = 'Hello';

for (let str of myString) {
  console.log(str);
}
H
e
l
l
o
  • 다른 점
let myString = 'Hello';
let myArray = ['H', 'e', 'l', 'l', 'o'];

console.log(typeof myString); // string
console.log(typeof myArray); // object
console.log(myString === myArray); // false
console.log(myString == myArray); // false
  • mutable vs immutable

가장 중요한 차이는 배열은 'mutable(바뀔 수 있는)' 자료형인 반면 문자열은 'immutable(바뀔 수 없는)' 자료형이라는 것이다. 배열은 요소에 접근해서 할당 연산자를 통해 요소를 수정할 수 있었지만, 문자열은 한 번 할당된 값을 수정할 수 없다. 즉, 변수에 할당된 문자열을 바꾸고 싶다면, 일부를 바꾸는 게 아니라 새로운 문자열을 지정해 주어야 한다.

// 배열은 mutable
let myArray = ['H', 'e', 'l', 'l', 'o'];
myArray[0] = 'B';
console.log(myArray); // ["B", "e", "l", "l", "o"]

// 문자열은 immutable
let myString = 'Hello';
myString[0] = 'B';
console.log(myString); // Hello

문자열이 가진 메소드들은 모두 return 값들을 활용하고, 본래의 문자열 값을 수정하지 않는다. 같은 의미에서 문장려에 splice 같은 메소드들은 사용할 수 없다.


6. 참조형 복사하기

객체랑 배열은 변수 = 주소값에 할당된다. 한 쪽을 수정하게 되면 다른 쪽도 자동으로 수정된다.

// 참조형 복사하기 (Reference Type Copy)
let number1 = [1, 2, 3];
let number2 = number1;

number2.push(4);

console.log(number1); // [1, 2, 3, 4]
console.log(number2); // [1, 2, 3, 4]

// 배열
let numbers1 = [1, 2, 3];
let numbers2 = numbers1.slice(); // 배열을 복사

numbers2.push(4);

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

// 객체1
let course1 = {
	title : '파이썬',
	language : 'Python'
};

let course2 = Object.assign({}, course1);

course2. title = '알고리즘';

console.log(course1); // {title: "파이썬", language: "Python"}
console.log(course2); // {title: "알고리즘", langauge: "Python"}

// 객체2
let course1 = {
	title : '파이썬',
	language : 'Python'
};

let course2 = {}

for (let key in course1) {
	course2[key] = course1[key];
};

course2. title = '알고리즘';

console.log(course1); // {title: "파이썬", language: "Python"}
console.log(course2); // {title: "알고리즘", langauge: "Python"}

// 객체3
function cloneObject(object) {
	let temp = {};

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

	return temp;
};

let course1 = {
	title : '파이썬',
	language : 'Python'
};

let course2 = cloneObject(course1);

course2. title = '알고리즘';

console.log(course1); // {title: "파이썬", language: "Python"}
console.log(course2); // {title: "알고리즘", langauge: "Python"}

7. 과거 변수 선언

자바스크립트에는 variable의 약자를 따서 var라는 키워드로 변수를 선언했을 때가 있었다.

(1) 중복 선언 허용

var 키워드로 선언한 변수의 첫 번째 문제는, letconst와는 다르게 중복 선언이 가능하다는 것이다. 똑같은 이름으로 변수를 한 번 더 선언하게 되면, 에러가 발생하는 것이 아니라 그냥 기존의 변수를 덮어버리게 된다. let 키워드로 선언한 변수에 값을 재할당하는 것과는 전혀 다른 것이다.

var myVariable = 'Hello!';
console.log(myVariable); // hello!
var myVariable = 'hello!';
console.log(myVariable); // Hello!

(2) 함수 스코프

var 키워드 변수가 사라진 두 번째 문제는 scope의 문제 때문이다. letconst 키워드로 선언한 변수는 if, for, function 등 어떤 키워드와 관계없이 코드 블록, 즉 {} 중괄호로 감싸진 부분을 기준으로 scope을 갖게 되지만, var 키워드로 선언한 변수는 scope가 function에서만 구분되어 있는다.

{
  let x = 3;
}

function myFunction() {
  let y = 4;
}

console.log(x);
console.log(y);
// Uncaught ReferenceError: x is not defined

{
  var x = 3;
}

function myFunction() {
  var y = 4;
}

console.log(x);
console.log(y);
// 3
// Uncaught ReferenceError: y is not defined

var 변수는 지역변수의 구분이 함수에만 있기 때문에 if, while, for, switch 등 다양한 상황에서 선언한 변수가 자칫, 전역변수의 역항르 하게 될 수 있다. 이렇게 함수를 기준으로만 적용되는 스코프를 함수 스코프, 코드 블록을 기준으로 적용되는 스코프를 블록 스코프라는 용어를 사용한다.

(3) 끌어올림 (Hoisting)

console.log(myVariable); // Uncaught ReferenceError: Cannot access 'myVariable' before initialization
let myVariable;

letconst로 선언한 변수는 선언되기 이전에 사용할 수 없다. 하지만 var 변수는 함수 스코프를 기준으로 선언되기 이전에도 변수에 접근이 가능하다.

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

이렇게 변수가 끌어올려 지는 현상을 '호이스팅(hoisting)'이라고 부른다. 호이스팅은 선언과 동시에 값을 할당하더라도, 선언문만 올려지기 때문에 값은 그대로 두 번째 줄에 남아있게 된다.

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

함수를 선언할 때도 이 호이스팅이 적용된다.

sayHi(); // hi

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

8. 간단한 퀴즈

  • 팩토리얼
// 방법 1
function factorial(n) {
  let result = 1;

  for (let i = 1; i <= n; i++) {
    result = result * i;
  }

  return result;
}

console.log(factorial(12));
console.log(factorial(6));
console.log(factorial(3));
console.log(factorial(0));

// 방법 2
function factorial(n) {
  let result = 1;

  for (let i = n; i >= 1; i--) {
    result = result * i;
  }

  return result;
}

console.log(factorial(12));
console.log(factorial(6));
console.log(factorial(3));
console.log(factorial(0));
  • 거스름돈 구하기
// 방법 1
function calculateChange(payment, cost) {
  let change = payment - cost; // 거스름돈 총액

  const fiftyCount = Math.floor(change / 50000);
  change = change - 50000 * fiftyCount;

  const tenCount = Math.floor(change / 10000);
  change = change - 10000 * tenCount;

  const fiveCount = Math.floor(change / 5000);
  change = change - 5000 * fiveCount;

  const oneCount = Math.floor(change / 1000);
  change = change - 1000 * oneCount;

  console.log(`50000원 지폐: ${fiftyCount}`);
  console.log(`10000원 지폐: ${tenCount}`);
  console.log(`5000원 지폐: ${fiveCount}`);
  console.log(`1000원 지폐: ${oneCount}`);
}

calculateChange(100000, 33000);
console.log('');
calculateChange(500000, 378000);

// 방법 2
function calculateChange(payment, cost) {
  let change = payment - cost; // 거스름돈 총액

  function billCounting(amount) {
    const count = Math.floor(change / amount);
    change = change - amount * count;
    return count;
  }

  const fiftyCount = billCounting(50000);
  const tenCount = billCounting(10000);
  const fiveCount = billCounting(5000);
  const oneCount = billCounting(1000);

  console.log(`50000원 지폐: ${fiftyCount}`);
  console.log(`10000원 지폐: ${tenCount}`);
  console.log(`5000원 지폐: ${fiveCount}`);
  console.log(`1000원 지폐: ${oneCount}`);
}

calculateChange(100000, 33000);
console.log('');
calculateChange(500000, 378000);
  • 팰린드롬
function isPalindrome(word) {
  for (let i = 0; i < Math.floor(word.length / 2); i++) {
    let left = word[i];
    let right = word[word.length - 1 - i];
    if (left !== right) {
      return false;
    }
  }
  return true;
}

console.log(isPalindrome("racecar"));
console.log(isPalindrome("stars"));
console.log(isPalindrome("기러기"));
console.log(isPalindrome("123321"));
console.log(isPalindrome("hello"));
console.log(isPalindrome("kayak"));
profile
프론트엔드 지식으로 가득찰 때까지

0개의 댓글