명확하게 의도를 가지고 타입을 변환.
타입 | 문자열 변환 결과 |
---|---|
undefined | "undefined" |
null | "null" |
boolean | true > "true", false > "false" |
number | 3 > "3" |
Symbol | 문자열로 변환을 시도하면 TypeError 에러 발생 |
BigInt | 3n > "3n" |
object | 객체를 원시 타입으로 변환 후 다시 ToString 추상 연산을 수행한 값을 반환. |
String()과 toString()의 차이점
null과 undefined는 toString()
을 사용하게 되면 TypeError 발생.
타입 | 숫자 변환 결과 |
---|---|
undefined | NaN |
null | +0 |
string | 숫자로 변경이 불가능한 값 > NaN, 숫자형 문자열 > 숫자 |
boolean | true > 1, false > 0 |
Symbol | 숫자로 변환을 시도하면 TypeError 에러 발생 |
BigInt | 숫자로 변환을 시도하면 TypeError 에러 발생 |
object | 객체를 원시 타입으로 변환한 후 다시 한 번 ToNumber 추상 연산을 수행한 값을 반환 |
parseInt() 함수
문자열만 대상으로 변환. 값이 문자열이 아닌 경우에는 해당 값을 문자열로 변환한 후 사용.
parseInt("10", 10) // 10
parseInt("-1", 10) // -1
두 번째 인자는 기수를 의미한다. 버그를 만들고 싶지 않다면 기수를 지정하는 것을 권장.
타입 | 불리언 변환 결과 |
---|---|
undefined | false |
null | false |
string | 빈 문자열 > false, 그 외 > true |
number | +0, -0, NaN > fasle / 그 외 숫자 > true |
Symbol | true |
BigInt | 0n > false, 그 외 BigInt 정수 > true |
object | true |
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 발생.const obj = {
valueOf() {
return 1
},
toString() {
return 'toString'
}
}
console.log(String(obj)) // 'toString'
console.log(Number(obj)) // 1
'a' > 'b' // true
'1' < '04' // false
['a'] < ['b'] // true
'1' < 2n // true
1 < true // false
1n < 2 // true
함수는 객체의 특별한 형태이며 문(statement)으로 구성된 몸체를 가진 하나의 실행 단위.
자바스크립트의 일급 함수(first-class function)로서 다른 함수의 매개변수나 반환 값으로도 사용할 수 있다.
다른 함수의 인자로 넘어가는 함수를 콜백 함수라고 부른다.
일급 함수는 아래와 같은 조건을 만족해야 한다.
- 변수에 함수를 할당할 수 있다.
- 함수를 인자로 전달할 수 있다.
- 함수를 반환 값으로 사용할 수 있다.
함수는 function 키워드로 정의되며 아래와 같은 구성 요소를 가지고 있다.
함수 선언문
함수의 이름이 반드시 정의되어야 한다.
함수 선언문에는 호이스팅이 발생하여 함수가 선언된 위치에서 코드의 최상단으로 끌어올려진다. 이 함수는 선언된 위치보다 상단에서 호출될 수 있다.
함수 표현식
함수의 이름이 선택 사항, 변수에 함수를 직접 할당
함수 표현식은 함수 선언문과 달리 호이스팅 되지 않기 때문에 변수에 함수를 할당하기 전에 호출할 수 없다.
return 문을 명시적으로 호출하지 않는다면 함수 호출의 결과 값은 undefined가 된다.
매개변수
매개변수 타입을 명시하지 않아도 되며, 인자의 값, 인자의 개수를 검사하지 않는다. 함수 호출 시 본래 정의된 매개변수보다 적은 수로 인자를 전달한다면 나머지 매개변수는 undefined 값으로 설정된다. 정의된 매개변수보다 많은 인자를 전달한다면 나머지 인자들은 무시된다.
인자와 매개변수는 동일한 의미 같지만 다르다. 인자는 함수 호출 시 전달되는 값, 매개변수는 함수에서 전달된 인자를 받아들이는 변수를 의미. 인자 = argument, 매개변수 = parameter
해체 할당과 매개변수 기본값
매개변수 해체 할당은 객체와 배열 모두 가능하며 프로퍼티가 없는 변수는 undefined를 할당 받는다. 매개변수에 해당하는 인자를 넘기지 않으면 매개변수의 값은 undefined로 설정된다. 만약 undefined가 아닌 기본값을 할당하고 싶은 경우 매개변수 기본값을 사용하여 지정할 수 있다.
arguments
화살표 함수를 제외한 모든 함수에서 arguments라는 객체를 사용할 수 있다. argumnets 객체를 사용하여 함수에 실제로 전달된 인자들을 참조할 수 있다. 또한 argumnets 객체는 유사 배열 객체이기 때문에 인덱스로 프로퍼티에 접근할 수 있으며, length 프로퍼티를 가지고 있다.
arguments 객체는 나머지 매개변수로 대체할 수 있다. 나머지 매개변수는 유사 배열 객체가 아닌 진짜 배열이기 때문에 인자들을 배열로 다루고 싶은 경우 유용하게 사용할 수 있다.
나머지 매개변수는 일반 매개변수와도 함께 사용할 수 있지만 반드시 마지막 매개변수만 나머지 매개변수가 될 수 있다.
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
가 변경된 함수는 call(), apply(), bind() 메서드를 사용해도 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'