기초부터 완성까지, 프론트엔드 4장 정리

당근 먹는 쿼카·2023년 1월 10일
0
post-thumbnail

4. 자바스크립트 기초 - 타입 변환과 함수

4.1 타입 변환

4.1.1 명시적 강제 변환

명확하게 의도를 가지고 타입을 변환.

  • 문자열로 변환
타입문자열 변환 결과
undefined"undefined"
null"null"
booleantrue > "true", false > "false"
number3 > "3"
Symbol문자열로 변환을 시도하면 TypeError 에러 발생
BigInt3n > "3n"
object객체를 원시 타입으로 변환 후 다시 ToString 추상 연산을 수행한 값을 반환.

String()과 toString()의 차이점
null과 undefined는 toString()을 사용하게 되면 TypeError 발생.

  • 숫자로 변환
타입숫자 변환 결과
undefinedNaN
null+0
string숫자로 변경이 불가능한 값 > NaN, 숫자형 문자열 > 숫자
booleantrue > 1, false > 0
Symbol숫자로 변환을 시도하면 TypeError 에러 발생
BigInt숫자로 변환을 시도하면 TypeError 에러 발생
object객체를 원시 타입으로 변환한 후 다시 한 번 ToNumber 추상 연산을 수행한 값을 반환

parseInt() 함수
문자열만 대상으로 변환. 값이 문자열이 아닌 경우에는 해당 값을 문자열로 변환한 후 사용.

parseInt("10", 10) // 10
parseInt("-1", 10) // -1

두 번째 인자는 기수를 의미한다. 버그를 만들고 싶지 않다면 기수를 지정하는 것을 권장.

  • 불리언으로 변환
타입불리언 변환 결과
undefinedfalse
nullfalse
string빈 문자열 > false, 그 외 > true
number+0, -0, NaN > fasle / 그 외 숫자 > true
Symboltrue
BigInt0n > false, 그 외 BigInt 정수 > true
objecttrue

4.1.2 객체의 원시 타입 변환

  • 문자열로 변환
    • 객체에 정의된 toString() 메서드를 호출. 별도로 정의한 toString() 메서드가 없다면 기본적으로 Object.prototype.toString() 메서드를 실행. Object.prototype.toString() 메서드는 결과 값으로 "[Object object]" 문자열을 반환
    • 첫 번째 결과가 원시 타입이라면 그 결과를 문자열로 변환하여 반환, 그렇지 않다면 valueOf() 메서드를 호출. valueOf() 메서드 역시 객체에 별도로 정의한 valueOf() 메서드가 없다면 기본적으로 Object.prototype.valueOf() 메서드를 실행.
    • valueOf() 메서드의 결과 값이 원시 타입이라면 그 결과를 문자열로 변환하여 반환, 그렇지 않다면 TypeError 발생.
  • 숫자로 변환
    • 객체에 정의된 valueOf() 메서드를 호출. 별도로 정의한 valueOf() 메서드가 없다면 기본적으로 Object.prototype.valueOf() 메서드를 실행. Object.prototype.valueOf() 메서드는 결과 값으로 객체를 그대로 반환.
    • 첫 번째 결과가 원시 타입이라면 그 결과를 수자로 변환하여 반환, 그렇지 않다면 toString() 메서드를 호출. 별도로 정의한 toString() 메서드가 없다면 기본적으로 Object.prototype.toString() 메서드를 실행.
    • toString() 메서드의 결과 값이 원시 타입이라면 그 결과를 숫자로 변환하여 반환, 그렇지 않다면 TypeError 발생.
  • 객체의 valueOf()와 toString()
const obj = {
  valueOf() {
    return 1
  },
  toString() {
    return 'toString'
  }
}

console.log(String(obj)) // 'toString'
console.log(Number(obj)) // 1

4.1.3 암시적 강제 변화

  • 덧셈 연산자
    • 피연산자 중 하나가 문자열 타입인 경우 나머지 타입도 문자열로 변환하여 병합.
    • 피연산자 중 하나가 객체이며 문자열로 변환 가능한 경우 문자열로 변환하여 연산.
    • 피연산자가 모두 문자열과 객체가 아닌 경우 숫자로 변환하여 연산. 만약 변환 결과의 타입이 각각 다른 경우 TypeError 발생.
  • 동등 연산자
    • 동등 연산자의 가장 큰 특징은 암시적 강제 변환을 허용.
    • 피연산자 중 하나는 문자열, 하나는 숫자인 경우 문자열을 숫자로 변환하여 동등함을 비교.
    • 피연산 중 하나는 문자열, 다른 하나는 BigInt인 경우 문자열을 BigInt로 변환하여 동등함을 비교.
    • 피연산자 중 하나는 null, 다른 하나는 undfined인 경우 동등하게 판단.
    • 피연산자 중 하나가 불리언일 경우 불리언을 숫자로 변환하여 동등함을 비교.
    • 피연산자 중 하나는 객체, 다른 하나가 문자열, 숫자, BigInt, 심볼 중 하나일 경우 객체를 원시 타입으로 변환하여 동등함을 비교.
    • 피연산자 중 하나는 숫자, 다른 하나는 BigInt인 경우 내부적인 숫자 비교 알고리즘에 따라 비교한 결과를 반환.
  • 비교 연산자
    • 문자열 비교
    'a' > 'b' // true
    '1' < '04' // false
    ['a'] < ['b'] // true
    • 문자열 외의 비교
    '1' < 2n // true
    1 < true // false
    1n < 2 // true
  • 비교 연산과 타입 변환
    • 다른 타입 간의 비교 연산에서 암시적인 강제 변환을 막을 수 없다.
    • 조건 표현식에서 암시적 강제 변환은 흔하게 사용된다. 모든 값은 불리언으로 변환되어 조건 표현식에서 평가된다.
    • 논리 연산자(&&, ||)
      • 논리 연산자의 결과 값이 불리언 타입이 아닐 수 있다.
      • && 논리 연산자는 첫 번째 피연산자의 값이 true로 평가되는 경우 두 번째 피연산자의 값을 반환, false로 평가되면 첫 번째 피연산자의 값을 반환.
      • || 논리 연산자는 첫 번째 피연산자의 값이 true로 평가되는 경우 첫 번째 피연산자의 값을 반환, false로 평가되면 두 번째 피연산자의 값을 반환.

4.2 함수

4.2.1 함수란 무엇인가?

함수는 객체의 특별한 형태이며 문(statement)으로 구성된 몸체를 가진 하나의 실행 단위.
자바스크립트의 일급 함수(first-class function)로서 다른 함수의 매개변수나 반환 값으로도 사용할 수 있다.
다른 함수의 인자로 넘어가는 함수를 콜백 함수라고 부른다.

일급 함수는 아래와 같은 조건을 만족해야 한다.

  • 변수에 함수를 할당할 수 있다.
  • 함수를 인자로 전달할 수 있다.
  • 함수를 반환 값으로 사용할 수 있다.

4.2.2 함수의 정의 방법

함수는 function 키워드로 정의되며 아래와 같은 구성 요소를 가지고 있다.

  • 함수의 이름(식별자): 함수를 할당할 변수의 이름
  • 함수의 매개변수: 매개변수는 괄호 안에서 쉼표로 분리, 함수의 몸체에서 지역 변수처럼 사용
  • 함수의 몸체: 중괄호 안에서 정의, 함수가 호출될 대마다 실행되는 문의 집합

함수 선언문
함수의 이름이 반드시 정의되어야 한다.
함수 선언문에는 호이스팅이 발생하여 함수가 선언된 위치에서 코드의 최상단으로 끌어올려진다. 이 함수는 선언된 위치보다 상단에서 호출될 수 있다.

함수 표현식
함수의 이름이 선택 사항, 변수에 함수를 직접 할당
함수 표현식은 함수 선언문과 달리 호이스팅 되지 않기 때문에 변수에 함수를 할당하기 전에 호출할 수 없다.


4.2.3 함수의 호출

return 문을 명시적으로 호출하지 않는다면 함수 호출의 결과 값은 undefined가 된다.


매개변수
매개변수 타입을 명시하지 않아도 되며, 인자의 값, 인자의 개수를 검사하지 않는다. 함수 호출 시 본래 정의된 매개변수보다 적은 수로 인자를 전달한다면 나머지 매개변수는 undefined 값으로 설정된다. 정의된 매개변수보다 많은 인자를 전달한다면 나머지 인자들은 무시된다.
인자와 매개변수는 동일한 의미 같지만 다르다. 인자는 함수 호출 시 전달되는 값, 매개변수는 함수에서 전달된 인자를 받아들이는 변수를 의미. 인자 = argument, 매개변수 = parameter

해체 할당과 매개변수 기본값
매개변수 해체 할당은 객체와 배열 모두 가능하며 프로퍼티가 없는 변수는 undefined를 할당 받는다. 매개변수에 해당하는 인자를 넘기지 않으면 매개변수의 값은 undefined로 설정된다. 만약 undefined가 아닌 기본값을 할당하고 싶은 경우 매개변수 기본값을 사용하여 지정할 수 있다.

arguments
화살표 함수를 제외한 모든 함수에서 arguments라는 객체를 사용할 수 있다. argumnets 객체를 사용하여 함수에 실제로 전달된 인자들을 참조할 수 있다. 또한 argumnets 객체는 유사 배열 객체이기 때문에 인덱스로 프로퍼티에 접근할 수 있으며, length 프로퍼티를 가지고 있다.
arguments 객체는 나머지 매개변수로 대체할 수 있다. 나머지 매개변수는 유사 배열 객체가 아닌 진짜 배열이기 때문에 인자들을 배열로 다루고 싶은 경우 유용하게 사용할 수 있다.
나머지 매개변수는 일반 매개변수와도 함께 사용할 수 있지만 반드시 마지막 매개변수만 나머지 매개변수가 될 수 있다.

4.2.4 화살표 함수

  • function 키워드를 생략
  • 매개변수가 하나인 경우 괄호를 생략할 수 있다
  • 함수 몸체에서 문이 하나인 경우 중괄호나 return 키워드를 생략할 수 있다.

4.2.5 this

this 는 읽기 전용 값으로 런타임 시 설정할 수 없다.
전역 실행 컨텍스트에서 this전역 객체를 참고한다.

function func() {
  console.log(this === window); // true
}

window.func()처럼 메서드 호출이 아닌 함수 직접 호출이기 때문에 함수의 컨텍스트가 어디에 속하는지 알 수 없기 때문에 undefined가 나와야 하는데 엄격 모드가 아닌 상태에서 this는 전역 객체를 참조하기 때문에 window와 같다는 값이 나옵니다. 그 문제를 해결하기 위해서는 엄격 모드를 사용해야 합니다. 'use strict' 지시문을 함수 본문 최상단에 작성하면 엄격 모드를 활성화할 수 있습니다.

function func() {
  'use strict'
  console.log(this === window) // false
  console.log(this === undefined) // true
}

new 키워드를 사용하여 생성한 함수인 생성자 함수의 this는 생성자 함수 내의 코드를 실행하기 전에 객체를 만들어 this에 바인딩 합니다. 생성된 객체는 생성자 함수의 prototype 프로퍼티에 해당하는 객체를 프로토타입으로 설정합니다. 이 객체는 이후 단계에서 this를 통해 계속 참조됩니다. 반환 값을 따로 명시하지 않아도 this에 바인딩한 객체가 반환됩니다. this가 아닌 다른 반환 값을 명시적으로 지정하였다면 this가 아닌 해당 값이 반환됩니다.

메서드를 호출하면 this는 해당 메서드를 소유하는 객체로 바인딩됩니다.

const obj = {
  name: 'quokka',
  greeting() {
    return `hello ${this.name}`;
  }
}
const greeting = obj.greeting
console.log(greeting()) // 'hello undefined'

메서드를 의도한 대로 사용하기 위해서는 반드시 해당 객체의 컨테스트로 명확하게 지정하여 호출하여야 합니다.


함수의 호출 방법에 상관없이 this를 특정한 객체로 바인딩하려면 내장 메서드인 call(), apply(), bind() 메서드를 이용하여 바인딩될 객체를 변경할 수 있습니다. 해당 방법을 명시적 바인딩 이라고 합니다.

call()

const obj = { name: 'quokka' }

function greeting() {
  return `Hello ${this.name}`
}

console.log(greetong.call(obj)) // 'Hello quokka'
const obj = { name: 'quokka' }

function userInfo(age, city) {
  return `name: ${this.name}, age: ${age}, city: ${city}`
}

console.log(userInfo.call(obj, 26, 'seoul')) // 'name: quokka, age: 26, city: seoul'

apply() call() 메서드와 동일하지만 전달할 인자들을 배열 형태로 전달해야 합니다.

const obj = { name: 'quokka' }

function userInfo(age, city) {
  return `name: ${this.name}, age: ${age}, city: ${city}`
}

console.log(userInfo.apply(obj, [26, 'seoul'])) // 'name: quokka, age: 26, city: seoul'

bind()

  • 함수의 this 바인딩을 영구적으로 변경 (생성자 함수로 사용되는 경우는 예외)
  • this가 변경된 함수는 call(), apply(), bind() 메서드를 사용해도 this 바인딩을 변경할 수 없음.
  • this를 바인딩하여 함수를 호출하는 것이 아니라 새로운 함수를 반환
  • 어디서 호출되는지에 상관없이 this 값을 고정하고 싶을 때 사용
const obj1 = { name: 'quokka' }
const obj2 = { name: 'rabbit' }

function userInfo(age, city) {
  return `name: ${this.name}, age: ${age}, city: ${city}`
}

const bound = userInfo.bind(obj1)

console.log(bound(26, 'seoul')) // 'name: quokka, age: 26, city: seoul'
console.log(bound.apply(obj2, [26, 'seoul'])) // 'name: quokka, age: 26, city: seoul'

0개의 댓글