컴퓨터 프로그램은 숫자 3.14나 텍스트 'Hello world' 같은 값을 조작하며 동작한다.
프로그래밍 언어에서 표현하고 조작할 수 있는 값의 종류를 타입이라 부르며,
어떤 타입을 지원하는지가 프로그래밍 언어의 가장 기본적인 특징을 이룬다.
프로그램에서 값을 나중에 사용하기 위해 유지하려면 변수에 값을 할당(저장)해야한다.
변수에는 이름이 있으며 프로그램은 변수 이름을 통해 값을 참조한다.
변수가 동작하는 방법 역시 프로그래밍 언어의 기본적인 특징 중 하나이다.
자바스크립트 타입은 기본 타입과 객체 타입으로 나뉜다.
기본 타입에는 숫자, 문자열, 불리언 타입이 있다.
특별한 값인 null
, undefined
는 기본 값이지만 숫자나 문자열, 불리언에 속하지 않는다.
각 값은 일반적으로 그 타입 자체로 취급해도 무방하다.
ES6에서는 특별한 목적을 가진 새 타입인 심벌을 추가했다.
심벌의 목적은 하위 호환성을 해치지 않으면서 언어의 확장을 정의하는 것이다.
숫자, 문자열, 불리언, null
, undefined
중 어느 것에도 속하지 않는 값은 모두 객체이다.
객체는 객체 타입의 멤버이며 프로퍼티의 집합이다.
각 프로퍼티에는 이름과 값이 있고, 이 값은 기본 값일 수도 있고 다른 객체일 수도 있다.
일반적인 자바스크립트 객체는 이름 붙은 값의 순서 없는 집합이다.
배열은 값의 순서 있는 집합이며 각 값은 숫자로 표현된다.(이름은 없다.)
기본적인 객체와 배열 외에도 Set 객체(값의 집합), Map 객체(키와 값의 연결), 형식화 배열(바이트 배열과 다른 이진 데이터 연결), ReExp 타입(텍스트 패턴, 문자열에서 정교한 매칭,검색,대체 동작 가능), Date 타입(날짜와 시간 표현 및 간단한 날짜 계산), Error 타입과 그 하위 타입(코드 실행 중 일어날 수 있는 에러)와 같은 유용한 객체 타입이 많다.
함수와 클래스는 구저 문법의 일부분이라고 볼 수는 없는데, 이점이 다른 정적 언어와의 차이점이다.
자바스크립트의 함수와 클래스는 그 자체가 값이므로 프로그램에서 조작할 수 있다.
기본값이 아닌 다른 값과 마찬가지로 함수와 클래스도 특별한 객체이다.
자바스크립트 인터프리터는 자동으로 가비지 컬력션을 수행해 메모리를 관리한다.
따라서 자바스크립트 프로그래머는 일반적으로 객체나 다른 값을 직접 파괴하거나 할당을 해제할 필요가 없다.
프로그램에서 어떤 값을 더는 참조하지 않게 되면 인터프리터는 그 값을 다시 사용할 수 없음을 인식하고 그 값이 차지하고 있던 메모리를 자동으로 다시 확보한다.
자바스크립트는 객체 지향 프로그래밍 스타일을 지원한다.
함수가 다양한 타입의 값을 다루는 것이 아니라 객체(타입 자체)에 그 값을 다루는 메서드를 정의한다.
// 배열 a의 요소를 정렬할 때 a를 sort() 함수에 전달하지 않고 메서드를 호출
a.sort(); // sort(a)의 객체 지향 버전
자바스크립트에서는 오직 객체만 메서드를 가질 수 있다.
하지만 숫자, 문자열, 불리언, 심벌도 마치 메서드가 있는 것처럼 동작한다.
메서드를 호출할 수 없는 값은 null
, undefined
뿐이다.
객체 타입은 가변 mutable
, 기본 타입은 불변 immutable
이다.
가변 타입의 값은 바뀔 수 있다. 객체 프로퍼티와 배열 요소의 값을 바꿀 수 있다.
불변 타입의 타입은 바뀔 수 없다. 문자열을 문자의 배열로 생각하면 바꿀 수 있다고 생각할 수 있지만, 변경 불가.
자바스크립트는 값의 타입을 자유롭게 변환한다.
예를 들어 프로그램에서 문자열이 와야 할 곳에 숫자를 쓰면 자바스크립트는 자동으로 그 숫자를 문자열로 변환한다.
값 변환 규칙은 동등성의 정의에 영향을 미친다.
프로그램에서는 상수와 변수의 이름을 통해 값을 참조한다.
상수는 const
로 선언하고 변수는 let
으로 선언한다.
상수와 변수에는 타입이 없고 선언할 때 어떤 값이 할당되는지 명시하지 않는다.
자바스크립트의 숫자 타입 Number는 정수와 함께 실수를 대략적으로 표현한다.
IEEE 745 표준에서 정의하는 64비트 부동 소수점 형식을 사용해 숫자를 표현한다.
이에 따라 최대 1.7976931348623157e+308, 최소 5e-324 범위의 숫자를 표현할 수 있다.
자바스크립트 숫자 형식은 -9007199254740991(-2⁵³) 이상, 9007199254740991(2⁵³) 이하 범위의 정수를 정확히 표현할 수 있다.
자바스크립트 프로그램에 직접 기입한 숫자를 숫자 리터럴이라 부른다.
10진 정수는 연속된 숫자로 표현한다.
0
3
1000000
16진수 리터럴은 0x
또는 0X
로 시작하며 그 뒤에 16진수 숫자를 쓴다.
16진수 숫자는 0부터 9까지 숫자나 a(A)부터 f(F)까지의 문자이며 문자는 10부터 15까지를 나타낸다.
0xfff // 255;
0xBADCAFE // 105939070;
ES6 이후 버전에서는 0b(0B)를 앞에 붙어 2진수, 0o(0O)를 앞에 붙어 8진수로 정수 표현이 가능하다.
0b10101 // 21;
0o377 // 255;
부동 소수점 리터럴에는 소수점이 포함될 수 있다.
즉, 실수의 전통적 문법을 사용한다.
값은 정수 부분, 소수점, 소수점 아래 부분을 순서대로 쓴다.
부동 소수점 리터럴은 지수 표기법으로도 표현할 수 있다.
이 표기법은 실수 다음에 e(E)를 쓰고 그 뒤에 선택 사항인 플러스 또는 마이너스 기호, 마지막으로 지수를 나타내는 정수를 쓰는 형식이다.
이 표기법은 실수에 10의 지수 승을 곱하는 방식으로 표현한다.
[digits][.digits][(E|e)[(+|-)]digits]
3.14
2345.6789
.333333333
6.02e23 // 6.02 x 10²³
자바스크립트는 산술 연산을 통해 숫자를 조작한다.
산술 연산자에는 덧셈 +
, 뺄셈 -
, 곱셈 *
, 나눗셈 /
, 나머지 %
, ES2016에 추가된 지수 **
가 있다.
이런 기본 산술 연산자 외에도 자바스크립트는 Math
객체의 프로퍼티로 정의된 함수와 상수를 통해 복잡한 계산을 지원한다.
Math.pow(2,10) // 1024; 2의 10승
Math.round(.6) // 1.0; 가장 가까운 정수로 반올림
Math.ceil(.6) // 1.0; 정수로 올림
Math.floor(.6) // 0.0; 정수로 내림
Math.abs(-5) // 5; 절대값
Math.max(x,y,z) // 인자중 가장 큰 값 반환
Math.min(x,y,z) // 인자중 가장 작은 값 반환
Math.random() // 0 이상 1.0미만의 랜덤 숫자
Math.PI // 원주율
Math.E // 자연 로그의 밑
Math.sqrt(3) // 3**0.5; 3의 세제곱근
Math.pow(3, 1/3) // 3**(1/3); 3의 세제곱근
Math.sin(0) // 삼각함수. Math.cos, Math.atan 등
Math.log(10) // 10의 자연로그
Math.log(100)/Math.LN10 // 100의 상용 로그
Math.log(512)/Math.LN2 // 512의 이진 로그
Math.exp(3) // Math.E의 세제곱
ES6에서 추가된 Math
객체 함수
Math.cbrt(27) // 3; 세제곱근
Math.hypot(3, 4) // 5; 인자의 제곱의 합의 제곱근
Math.log10(100) // 2; 상용 로그
Math.log2(1024) // 10; 이진 로그
Math.log1p(x) // 1+x의 자연 로그.
Math.expm1(x) // Math.exp(x)-1; Math.log1p()의 역
Math.sign(x) // 인자의 부호에 따라 -1, 0, 1 반환
Math.imul(2,3) // 6; 32비트 정수의 곱셈
Math.clz32(0xf) // 28; 32비트 정수에서 맨 앞으 0비트 개수
Math.trunc(3.9) // 3; 소수점 아래를 잘라 내어 정수로 변환
Math.fround(x) // 가장 가까운 32비트 부동 소수점 숫자로 반올림
Math.sinh(x) // 하이퍼볼릭 사인 Math.cosh(), Math.tanh() 등
Math.asinh(x) // 하이퍼볼릭 아크사인 Math.acoch(), Math.atanh() 등
자바스크립트는 산술 연산 과정에 0으로 나누거나 오버플로, 언더플로가 발생해도 에러를 일으키지 않는다.
계산 결과가 자바스크립트가 표현할 수 있는 가장 큰 숫자보다 큰 경우(오버플로)에는 특별한 값 Infinity
를 반환.
마찬가지로 음수의 절대값이 자바스크립트가 표현할 수 있는 가장 큰 음수의 절대값보다 크다면 결과는 음의 무한대 -Infinity
.
무한한 값에 다른 숫자를 더하거나, 빼거나, 곱하거나, 나누더라도 결과는 여전히 무한한 값이다.
언더플로는 계산 결과가 자바스크립트가 표현할 수 있는 가장 작은 숫자보다도 0에 가까울 때 일어난다.
자바스크립트는 이 경우 0을 반환한다.
음수에서 언더플로가 일어나면 '음의 0'이라는 특별한 값을 반환. 이 값은 일반적인 0과 거의 완전히 같다.
자바스크립트는 0으로 나눠도 에러가 일어나지 않는다. 무한대 또는 음의 무한대를 반환하는데, 한 가지 예외가 있다.
0을 0으로 나누는 경우는 정의되어 있지 않으므로 이 결과는 특별한 값 NaN(Not a Number)
가 반환.
무한대를 무한대로 나누거나, 음수의 제곱근을 추가하거나, 숫자가 아니고 숫자로 변환할 수도 없는 피연산자에 산술 연산자를 적용하려 할 때도 NaN
이 반환된다.
NaN
은 자기 자신을 포함해 어떤 값과도 같지 않다는 특징이 있다.
즉, x
변수의 값이 NaN
인지 알아보기 위해 x === NaN
과 같은 표현식을 쓸 수 없다는 이야기이다.
따라서, x != x
또는 Number.isNaN(x)
를 사용해야 한다.
자바스크립트의 Infinity
, NaN
은 전역 상수이며 이들은 Number
객체의 프로퍼티로도 존재한다.
Infinity // 표현하기에 큰 양수
Number.POSITIVE_INFINITY // 같은 값
1/0 // Infinity
Number.MAX_VALUE * 2 // Infinity, 오버플로
-Infinity // 표현하기에 큰 음수
Number.NEGATIVE_INFINITY // 같은 값
-1/0 // -Infinity
-Number.MAX_VALUE * 2 // -Infinity
NaN // 숫자가 아닌 값
Number.NaN // NaN과 같으며 표현이 다름
0/0 // NaN
Infinity/Infinity // NaN
"Hello"/1 // NaN
Number.MIN_VALUE/2 // 0; 언더플로
-Number.MIN_VALUE/2 // -0; 음의 0
-1/Infinity // -0; 음의 0
-0
// ES6에서 정의된 Number 프로퍼티
Number.parseInt() // 전역함수 parseInt()와 같다
Number.parseFloat() // 전역함수 parseFloat()와 같다
Number.inNaN(x) // x는 NaN?
Number.isFinite(x) // x는 유한한 숫자?
Number.isInteget(x) // x는 정수?
Number.isSafeInteger() // x는 -(2**53)보다 크고 2**53보다 작은 정수?
Number.MIN_SAFE_INTEGER // -(2**53 - 1);
Number.MAX_SAFE_INTEGER // 2**53 - 1;
Number.EPSILON // 2**53; 숫자를 구별할 수 있는 가장 작은 차이
음의 0은 통상적인 값이 아니다.
이 값은 일치 연산자 ===
로 양의 0과 비교해도 true
를 반환하므로 두 값에 차이가 없다고 해도 무방하지만,
아래와 같이 제수(분모)로 사용될 때는 예외이다.
let zero = 0; // 일반적인 0
let negz = -0; // 음의 0
zero === negz // true; 0과 음의 0은 일치한다.
1/zero === 1/negz // false; Infinity와 -Infinity는 일치하지 않는다.
실수는 무한히 많지만, 자바스크립트의 부동 소수점 형식으로 정확히 표현할 수 있는 숫자는 유한하다.
따라서 자바스크립트로 실수를 다룰 때 실제 숫자의 근삿값으로 표현될 때가 자주 있다.
자바스크립트를 비롯해 최신 프로그래밍 언어에서 사용하는 IEEE 754 부동 소수점 표현은 이진 표현이며,
1/2, 1/8, 1/1024
같은 분수는 정확히 표혈할 수 있다.
하지만, 이진 부동 소수점 표현은 0.1
같은 단순한 숫자를 정확히 표현하지 못한다.
자바스크립트 숫자는 정밀한 편이며 0.1
을 가깝게 아주 가깝게 표현한다.
하지만 가까울 뿐 정확한것은 아니기 때문에 문제가 발생할 수 있다.
let x = .3 - .2;
let y = .2 - .1;
x === y // false; 두 값은 일치하지 않는다.
x === .1 // false; 0.3 - 0.2는 0.1과 같지 않다.
y === .1 // true; 0.2 - 0.1는 0.1이다.
반올림 오류 떄문에 0.3과 0.2의 차이의 근삿값은 0.2와 0.1의 차이의 근삿값과 같지 않다.
이 문제는 자바스크립트만의 문제가 아닌 이진 부동 소수점 숫자를 사용하는 프로그래밍 언어에서 모두 발생한다.
또한 위 코드의 x
와 y
는 서로 아주 가깝고, 정확한 값(0.1)에도 마찬가지로 아주 가깝다.
계산된 값은 목적에 알맞게 사용할 수 있을 만큼 정확하지만, 일치 여부를 비교할 때 문제가 발생한다.
BigInt는 ES2020에서 정의한 자바스크립트의 최신 기능이며 값이 정수인 숫자 타입이다.
이 타입은 다른 프로그래밍 언어나 API와의 호환에 필요한 64비트 정수를 표현하기 위해 추가되었다.
BigInt 값은 수천 자리, 심지어 수백만 자리까지 커질 수 있고, 타이밍 공격을 방지할 수 없으므로 암호화에 사용할 수 없다.
BigInt 티터럴은 연속된 숫자 다음에 소문자 n을 붙인 형식이다.
BigInt는 기본적으로 10진수지만, 0b
, 0o
, 0x
를 앞에 붙여 이진, 8진, 16진수 BigInt를 만들 수 있다.
1234n
0b111111n // 이진 BigInt
0o777n // 8진 BigInt
0x8000000000000000n // 2n**63n; 64비트 정수
BigInt()
함수를 써서 일반적인 자바스크립트 숫자나 문자열을 BigInt로 변환할 수 있다.
BigInt(Number.MAX_SAFE_INTEGER) // 9007199254740991n
let string = "1" + "0".repeat(1000) // 1 뒤에 0이 100개
BigInt(string) // 10n**100n
BigInt 값의 산술 연산은 일반적인 자바스크립트 숫자의 산술 연산과 비슷하지만,
나눗셈을 할 때 나머지를 버린다는 점이 다르다.
1000n + 2000n // 3000n;
3000n - 2000n // 1000n;
2000n * 6000n // 6000000n;
3000n / 997n // 3n; 몫은 3
3000n % 997n // 9n; 나머지는 9
(2n ** 131071n) - 1n // 39457 자리의 메르센 소수(2en -1 꼴의 수 중에서 소수인 것)
BigInt에 +
, -
, *
, /
, %
, **
같은 표준 연산자를 쓸 수 있긴 하지만, BigInt 피연산자와 일반적인 숫자 피연산자를 섞어 쓸 수는 없다.
어떤 숫자 타입이 다른 숫자 타입보다 더 광범위하다면 피연산자가 섞였을 때 더 광범위한 타입의 값을 반환하도록 산술 연산을 정의하기는 쉽다. 하지만 이 경우는 어느 타입도 다른 타입에 비해 더 광범위하지 않다.
BigInt는 대단히 큰 값을 표현할 수 있으므로 이런 면에서는 일반적인 숫자보다 더 광범위하다고 말할 수 있겠지만,
BigInt는 단지 정수만 표현할 수 있으므로 이런 면에서는 일반적인 자바스크립트 숫자가 더 광범위하다고 말할 수도 있다.
반면 비교 연산자는 피연산자를 섞어도 괜찮다.
1 < 2n // true;
2 > 1n // true;
0 == 0n // true;
0 === 0n // false;
자바스크립트의 Date
클래스는 날짜와 시간에 대응하는 숫자를 표현하고 조작한다.
Date
는 객체이지만 타임스탬프인 숫자 표현 역시 가지고 있으므로 1970년 1월 1일로부터 몇 밀리초가 지났는지 계산이 가능하다.
let timestamp = Date.now(); // 현재 시간을 타임스탬프 형식으로 표시
let now = new Date(); // 현재 시간을 Date 객체로 표시
let ms = now.getTime(); // 밀리초 타임스탬프로 변환
let iso = now.toISOString(); // 표준 형식의 문자열로 변환
자바스크립트에서 텍스트를 표현하는 타입은 문자열이다.
문자열은 16비트 값이 순서에 따라 이어진 형태이며, 기본 값이므로 불변이다.
각 값은 일반적으로 유니코드 문자이고, 문자열의 길이는 그 문자열에 포함된 16비트 값의 개수이다.
자바스크립트 문자열과 그 배열 형태의 위치(인덱스)는 0에서 시작하며 첫 번째 16비트의 값은 0번 위치, 두 번째는 1번 위치 등으로 이어진다.
빈 문자열은 길이가 0인 문자열이다.
자바스크립트에서 문자열을 사용할 때는 그 문자열을 앞뒤가 맞는 작은따옴표 (''), 큰따옴표 (""), 백틱 (``)으로 묶으면 된다.
작은따음표로 감싼 문자열 안에 큰따옴표나 백틱을 쓸 수 있다. 큰따옴표나 백틱으로 감싼 문자열도 같다.
백틱으로 감싼 문자열은 ES6 기능이며 문자열 리터럴 안에 자바스크립트 표현식을 넣을 수 있다.
이 문법을 보간(interpolation)이라고 한다.
자바스크립트 최초 버전은 문자열 리터럴을 단 한줄에만 쓸 수 있게 규정했으므로 코드에서 긴 문자열을 표현하기 위해 +
연산자로 문자열을 합치는 경우가 많았다.
ES5부터는 각 행의 마지막에 역슬래시()를 써서 문자열 리터럴을 여러 행으로 구분할 수 있다.
이 표기법을 사용할 경우, 역슬래시나 줄 끝 문자는 문자열 리터럴에 포함되지 않는다.
작은따옴표나 큰따옴표로 감싼 문자열 리터럴안에 뉴라인 문자를 써야 할 때는 문자열 시퀀스 \n
을 쓰면 된다.
ES6 백틱 문법 역시 문자열을 여러 행으로 나누어 쓸 수 있는데, 이 경우에는 줄 끝 문자가 문자열 리터럴에 포함된다.
// 두 행을 한 행으로 표현
'two\nlines'
// 한 행을 세 행으로 나눔
"one\
long\
line"
// 두 행 문자열을 두 행에 나눔
`이 행의 마지막에 있는 줄바꿈 문자는
있는 그대로 문자열의 일부이다.`
작은따옴표로 문자열을 감쌀 때는 can't 나 O'Reilly's 같은 영어 단축 표현 또는 소유격을 주의.
아포스트로피는 작은따옴표와 같으므로 작은따옴표로 감싼 문자열 안에 아포스트로피를 쓸 때는 반드시 역슬래시로 이스케이프 해야한다.
클라이언트 사이드 자바스크립트 프로그래밍에서는 자바스크립트 코드에 HTML 문자열이 들어갈 수 있고, HTML 안에 자바스크립트 코드가 들어갈 수 있다.
따라서 자바스크립트와 HTML을 섞어 쓸 때는 따옴표를 구분하는 규칙을 정해두는게 좋다.
<!-- 자바스크립트 표현식 '' | HTML 표현식 "" -->
<button onclick="alert('Thank you')">Click</button>
문자열에서의 역슬래시는 특별한 의미를 갖는다.
역슬래시는 그 다음 문자와 조합해서 일반적인 방법으로는 문자열에 표시할 수 없는 문자를 표현한다.
작은따옴표(아포스트로피)를 이스케이프하는 \'
.
이 이스케이프 시퀀스는 작은따옴표로 감싼 문자열 리터럴에 아포스트로피를 써야할 때 유용하다.
이스케이프 시퀀스라는 말은 역슬래시를 써서 작은따옴표로 감싸인 문자의 일반적인 해석 방법을 벗어단다(이스케이프한다)는 의미이다.
시퀀스 | 표현하는 문자 |
---|---|
\0 | NUL 문자 (\u0000) |
\b | 백스페이스 (\u0008) |
\t | 탭 (\u0009) |
\n | 뉴라인 (\u000A) |
\v | 세로 탭 (\u000B) |
\f | 폼 피드 (\u000C) |
\r | 캐리지 리턴 (\u000D) |
\" | 큰따옴표 (\u0022) |
\' | 작은따옴표(아포스트로피) (\u0027) |
\ | 역슬래시 (\u005c) |
\xnn | 16진수 숫자 두 개 nn으로 표현하는 유니코드 문자 |
\unnnn | 16진수 숫자 네 개 nnnn으로 표현하는 유니코드 문자 |
\u{n} | 코드 포인트 n으로 표현하는 유니코드 문자. 여기서 ndms 0에서 10FFFF 범위에 있는 16진수 숫자. |
위 표의 마지막 세 가지 이스케이프 시퀀스는 범용적이며 그 뒤에 유니코드 문자 코드를 16진수 숫자로 써서 어떤 문자든 표현할 수 있다.
\xA9
는 저작권 기호, 16진수 숫자 A9가 유니코드 인코딩을 나타냄\u
이스케이프도 임의의 유니코드 문자를 표현함. 이 뒤에는 16진수 숫자를 네 개 쓰거나,
중괄호 안에 16진수 숫자를 1~6개 쓰는 두가지 형식
\u03c0
은 π
문자\u{1f600}
은 웃는 얼굴 이모지위 표에 없는 문자 앞에 역슬래시를 쓰면 그 역슬래시는 무시된다.(#는 #과 동일)
ES5부터는 줄바꿈 앞에 역슬래시를 삽입해 문자열 리터럴을 여러 행으로 나눠 쓰는 표기법을 허용한다.
자바스크립트에는 문자열을 '병합(연결)'하는 기능이 내장되어 있다.
+
연산자를 숫자와 함께 쓰면 이 연산자는 숫자를 더하지만,
문자열에 쓰면 두 번째 문자열을 첫 번째 문자열 뒤에 이어 붙인다.
let msg = "Hello, " + "world"; // 문자열 "Hello, world"
let greeting = "Welcome to my blogm," + " " + name;
문자열을 비교할 때눈 일치 연산자와 불일치 연산자가 표준이다.
두 문자열이 정확히 같은 16비트 값의 연속으로 이루어졌을 때에만 일치한다.
문자열은 <
, <=
, >
, >=
연산자로 비교할 수도 있다.
문자열 비교는 16비트 값을 비교하는 방식으로 이루어진다.
문자열의 길이, 즉 그 안에 포함된 16비트 값의 개수는 length
프로퍼티로 알 수 있다. str.length
자바스크립트에는 length
프로퍼티 외에도 다양한 문자열 API가 있다.
let s = "Hello, world";
// 문자열 일부 가져옴
s.substring(1, 4) // "ell"; 인덱스 번호가 1번부터 4번까지인 문자
s.slice(1,4) // "ell"; 인덱스 번호가 1번부터 4번까지인 문자
s.slice(-3) // "rld"; 마지막 세 문자
s.split(", ") // ["Hello", "world"]; 구분자(", ")를 기준으로 나눔
// 문자열 검색
s.indexOf("l") // 2; l이 처음 나타나는 위치
s.indexOf("l", 3) // 3 3번 문자부터 시작해 l이 처음 나타나는 위치
s.indexOf("zz") // -1; zz라는 문자열이 없음
s.lastIndexOf("l") // 10; 1이 마지막으로 나타나는 위치
// 불리언 타입을 반환하는 검색 함수 (ES6에서 추가)
s.startsWith("Hell") // true; s는 Hell로 시작
s.endsWith("!") // false; s는 !로 끝나지 않음
s.includes("or") // true; s에 or이 포함되어있음
// 문자열 변경
s.replace("llo", "ya") // "Heya, world";
s.toLowerCase() // "hello, world";
s.toUpperCase() // "HELLO, WORLD";
s.normalize() // 유니코드 NFC 정규화, ES6에서 추가
s.normalize("NFD") // NFD 정규화. NFKC, NFKD도 있다.
// 문자열의 각 16비트 문자를 검사
s.charAt(0) // "H"; 첫 번째 문자
s.charAt(s.length - 1) // "d"; 마지막 문자
s.charCodeAt(0) // 72; 주어진 위치의 16비트 숫자
s.codePointAt(0) // 72; 16비트보다 큰 코드 포인트에서 동작하는 ES6 기능
// 패딩 함수 (ES2017에서 추가)
"x".padStart(3) // " x"; 왼쪽에 스페이스를 세 개 더함
"x".padEnd(3) // "x. "; 오른쪽에 스페이스를 세 개 더함
"x".padStart(3, "*") // "**x"; *를 왼쪽에 붙여 길이를 3에 맞춤
"x".padEnd(3, "-") // "x--"; -를 오른쪽에 붙여 길이를 3에 맞춤
// 공백 제거. trim()은 ES5 기능, 나머지는 ES2019 가능
" test".trim() // "test"; 앞뒤 공백 제거
" test".trimStart() // "test "; 왼쪽 공백 제거. trimLeft()
" test".trimEnd() // " test"; 오른쪽 공백 제거. trimgRight()
// 그 외
s.concat("!") // "Hello, world!"
"<>".repeat(5) // "<><><><><>" n번 복사. ES6에서 추가
자바스크립트의 문자열은 불변이기 때문에 replace()
나 toUpperCase()
같은 메서드는 기존 문자열을 수정하는 것이 아니라 새 문자열을 반환하는 것이다.
문자열은 읽기 전용 배열로 취급할 수도 있으며, 아래와 같이 chartAt()
메서드 대신 대괄호를 써서 문자열의 개별 문자(16비트 값)에 접근할 수 있다.
let s = "hello, wolrd"
s[0] // "h";
s[s.length - 1] // "d";
ES6부터는 백틱으로 감싼 문자열 리터럴을 사용할 수 있다.
let s = `hello, world`;
하지만 이것은 일반적인 문자열 리터럴 문법과는 다르게, 임의의 자바스크립트 표현식을 넣을 수 있는 템플릿 리터럴이다.
백틱으로 둘러싼 문자열 리터럴의 최종값은 그 안에 포함된 표현식을 평가해서 그 표현식의 값을 문자열로 변환한 다음, 변환된 문자열을 백틱 안에 들어 있는 리터럴 문자와 결합한 값으로 결정된다.
let name = "Bill";
let greeting = `Hello ${name}.`; // "Hello Bill";
${}
안에 있는 것은 모두 자바스크립트 표현식으로 해석되고, 중괄호 밖에 있는 것은 모두 일반적인 문자열 리터럴 텍스트이다.
중괄호 안의 표현식을 평가하고 문자열로 변환한 후 템플릿에 삽입할 때 달러 기호와 중괄호, 그 안에 있는 것을 대체한다.
템플릿 리터럴 안에 쓸 수 있는 표현식 개수에는 제한이 없다.
일반적인 문자열에 쓸 수 있는 이스케이프 문자는 전부 쓸 수 있고, 특별한 이스케이프 없이 몇행에 걸쳐 써도 무방하다.
let errorMessage = `\
\u2718 Test failure at ${filename}:${linenumber}:
${exception.message}
Stack trace:
${exception.stack}
`
위 예제의 첫 번째 행 마지막에 있는 역슬래시는 줄바꿈 문자를 이스케이프 하므로 결과 문자열은 줄바꿈 없이 유니코드 문자 \u2718
으로 시작한다.
템플릿 리터럴에는 강력하지만 잘 사용되지 않는 기능이 하나 있다.
여는 백틱 바로 앞에 함수 이름(태그)이 있으면 템플릿 리터럴의 텍스트와 표현식 값이 함수에 전달된다.
그리거 이 태그된 템플릿 리터럴의 값이 함수의 반환 값이다.
이 기능은 HTML이나 SQL을 텍스트에 붙이기 전에 이스케이프하는 용도로 사용할 수 있다.
ES6에는 내장된 태그 함수 String.raw()
가 있다.
이 함수는 역슬래시 이스케이프를 처리하지 않고 백틱 안의 텍스트를 반환한디ㅏ.
`\n`.length // 1; 이 문자열에는 뉴라인 문자 하나만 있다.
String.raw`\n`.length // 2; 역슬래시 문자와 n
태그된 템플릿 티러럴의 태그 부분이 함수임에도 불구하고 괄호 없이 호출되었다.
여기에서는 백틱 문자가 여닫는 괄호를 대신했다.
템플릿 태그 함수를 자유롭게 정의할 수 있다는 것은 자바스크립트의 강력한 기능 중 하나이다.
이런 함수는 문자열을 반환할 필요가 없으며, 마치 새로운 리터럴 문법을 정의하는 것처럼 생성자로 사용할 수 있다.
자바스크립트에는 문자열 내부의 패턴을 정의하고 매칭하는 정규 표현식(RegExp)이라는 데이터 타입이 있다.
RegExp는 사실 자바스크립트의 기본적인 데이터 타입은 아니지만, 숫자나 문자열과 마찬가지로 리터럴 문법이 있으므로 기본적인 데이터 타입처럼 보이기도 한다.
정규 표현식 티러럴 문법은 복잡하며 그 API 역시 간단하지 않지만 매우 강력하고 텍스트 처리에 자주 사용된다.
정규 표현식 리터럴은 슬래시 한 쌍 사이에 텍스트를 쓰는 형태이다.
두 번째 슬래시 뒤에도 글자 하나 이상 쓸 수 있으며 이 글자는 패턴의 의미를 수정한다.
/^HTML/; // 문자열의 시작 부분에 있는 H T M L에 일치한다.
/[1-9][0-9]*/; // 0이 아닌 숫자가 하나 있어야 하고, 그 뒤의 숫자는 제한이 없다.
/\bjavascript\b/i; // javascript가 한 단어로 들어가야하고 대소문자를 구분하지 않는다.
RegExp 객체에는 유용한 메스드가 많고 문자열 역시 RegExp 인자를 받는 메서드가 있다.
let text = "testing: 1, 2, 3"; // 샘플 텍스트
let pattern = /\d+/g; // 연속된 숫자 전체에 일치한다.
pattern.test(text) // true; 패턴에 맞는 것이 있다.
text.search(pattern) // 9; 첫 번쨰로 일치하는 부분의 위치
text.match(pattern) // ["1", "2", "3"]; 일치하는 부분이 모두 포함된 배열
text.replace(pattern, "#") // "testing: #, #, #";
text.split(/\D+/) // ["", "1", "2", "3"]; 숫자가 아닌 것에서 나눔