ES6 (3)

Y·2020년 9월 30일
0

ES6

목록 보기
3/6

ES6는 자바스크립트 내장 객체에 많은 새로운 프로퍼티와 메서드를 업데이트 했다. 이 포스팅에서는, 자바스크립트 네이티브 객체에 추가 된 여러 기능들에 대해 알아볼 것이다.

숫자


ES6는 숫자를 이용한 작업을 더 수월하게 하기 위하여 Number객체에 다양한 새로운 프로퍼티와 숫자 생성 방식을 추가했다.

2진수


ES5 에서는 숫자를 이진법으로 표현하는 네이티브한 방식이 없었지만, ES6에서는 0b토큰을 이용하여 자바스크립트가 인터프리팅 할 수 있게 업데이트 되었다.

let a = 0b00001111;
let b = 15;
console.log(a === b); // true
console.log(a); // 15

8진수


ES5 에서는 8진법 표현을 하기 위해서는 0으로 시작하는 숫자를 이용했다.

var a = 017;
var b = 15;
console.log(a === b); // true
console.log(a); // 15

하지만 017이라는 표현은 자칫 17로 해석 할 수 있는 여지가 있었으며, 따라서 ES6에서는 0o 토큰을 이용하여 자바스크립트가 팔진수로 인터프리팅 할 수 있게 업데이트 되었다.

let a = 0o17;
let b = 15;
console.log(a === b); // true
console.log(a); // 15

Number.isNaN(value)


ES5 에서는 변수가 NaN 값을 가지고 있는지 여부를 판단할 수 없었다.

ES6 에서는 Number 객체의 새로운 메서드로 isNaN()을 제시하였으며, 이는 인수가 NaN인지 아닌지의 여부를 불린값으로 반환한다.

let a = "NaN";
let b = NaN;
let c = "hello";
let d = 12;
console.log(Number.isNaN(a)); // false
console.log(Number.isNaN(b)); // true
console.log(Number.isNaN(c)); // false
console.log(Number.isNaN(d)); // false
console.log(isNaN(a)); // true
console.log(isNaN(b)); // true
console.log(isNaN(c)); // true
console.log(isNaN(d)); // false

여기서 전역객체의 isNaN()은 인수가 숫자인지 아닌지의 여부를 불린 값으로 반환한다. 숫자면 false, 숫자가 아니면 true를 반환한다.

Number.isSafeInteger(number)


자바스크립트 숫자는 64비트 이진부동소수점의 형태로 저장되며, 국제 IEEE-754 표준을 따른다. 분수는 0~51 비트, 지수는 52~62비트, 나머지에 사인이다. 따라서 자바스크립트에서는 이 표준을 따르며 정확히 표현될 수 있는 범위안의 정수를 SafeInteger라고 부르며, 이 메서드는 이를 판별하기 위한 메서드이다.
-(2^53 - 1) ~ (2^53 -1) 사이가 안전한 정수값이라고 한다.

console.log(Number.isSafeInteger(156)); // true
console.log(Number.isSafeInteger('1212')); // false
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
console.log(Number.isSafeInteger(Number.MIN_SAFE_INTEGER)); // true
console.log(Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1)); // false

여기서 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER은 ES6에서 소개된 각 안전한정수의 최대, 최소값이다.

Number.EPSILON


자바스크립트는 이진부동소수점을 이용하며, 0.1, 0.2 와 같은 수를 사용하게되면, 가장 가까운 정수의 형태로 round되며, 이는 에러를 유발할 수 있다.

console.log(0.1 + 0.2 == 0.3); // false
console.log(0.9 - 0.8 == 0.1); // false
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.9 - 0.8); // 0.09999999999999998

Number.EPSILON 프로퍼티는 ES6에서 새로 등장한 프로퍼티로, 이 프로퍼티는 약 2^-52의 값을 가지고 있다. 이 숫자는 부동소수점 계산을 할 때, 합리적인 오차범위로 사용될 수 있다.

functionepsilonEqual(a, b)
{
 return Math.abs(a - b) <Number.EPSILON;
}
console.log(epsilonEqual(0.1 + 0.2, 0.3)); // true
console.log(epsilonEqual(0.9 - 0.8, 0.1)); // true

문자열


ES6는 문자열을 생성하는 새로운 방식을 제공하고, 전역 String 객체에 새로운 프로퍼티를 추가함으로서 문자열을 이용한 작업을 더 수월하게 해준다.

자바스크립트의 인코딩과 이스케이프 시퀀스에 대해서 먼저 알아보자. Unicode Character set에서는 모든 문자는 code point라는 10진수를 기반으로 표현된다. code unitcode point를 저장하기위한 메모리의 비트로 고정된 숫자다. code unitUTF-8 또는 UTF-16 같이 어떤 스키마가 사용되는가에 따라 8비트 또는 16비트다. 만약 code pointcode unit에 맞지 않으면 이는 복수의 code unit으로 스플릿되고, 복수의 문자들이 순서대로 쓰여 한개의 문자를 표현한다.

자바스크립트 디폴트 인터프리터는 자바스크립트 소스코드를 UTF-16 code unit의 시퀀스로 인터프리트 한다. 만약 소스코드가 UTF-8 인코딩 스키마로 작성되면, 자바스크립트 인터프리터 다양한 방식으로 UTF-8 code unit로 인터프리트 할 수 있도록 한다. 자바스크립트에서 문자열은 항상 UTF-16 code points 시퀀스이다.

유니코드는 세계의 주요한 문자 언어를 교환하고 표현하기 위한 문자-코딩 표준입니다. 유니코드는 아메리카, 유럽, 중동, 아프리카, 인도, 아시아, 태평양 지역(Pacifica)의 언어를 포함하며 고문자와 기술 분야 기호들도 포함합니다. 유니코드는 공통적인 기술 분야, 수학 분야 기호 뿐만 아니라 여러 언어를 포함한 텍스트의 교환, 처리, 표현을 지원합니다. 유니코드는 나라마다 서로 다른 문자 표준으로 인해서 여러 언어를 포함했을 때 발생하는 국제화 문제를 해결할 수 있기를 희망합니다. 하지만 아직은 모든 현대 문자, 고대 문자를 지원하지는 못합니다.
유니코드 문자 집합은 알려진 모든 인코딩을 위해 사용될 수 있습니다. 유니코드는 ASCII (American Standard Code for Information Interchange, 정보 교환을 위한 미국 표준 코드) 문자 집합을 본떠 만들어졌습니다. 각각의 문자에 숫자와 이름을 부여한 것입니다. 문자 인코딩은 문자의 정체성(identity)과 숫자 값(코드 위치)와 함께 숫자 값의 비트 표현을 명시합니다. 16비트 숫자 값(코드 값)은 U+0041처럼 접두어 U뒤에 16진수를 붙여서 표시합니다. 이 값의 유일한 이름은 LATIN CAPITAL LETTER A입니다.

출처: https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Unicode

어떤 유니코드 문자던, 65536 미만의 코드포인트의 유니코드 문자는 자바스크립트 문자열 또는 16진수 코드포인트를 사용한 소스코드에서 이스케이프 될 수 있고, 이는 \u 접두사를 사용한다.

Escaping Larger code points


ES5에서는 16비트 이상을 요구하는 문자의 이스케이프 경우, 두개의 유니코드를 사용했다. 가령, \u1F691를 문자열에 추가하기 위해서는 다음과 같은 방식으로 이스케이프한다.

console.log("\uD83D\uDE91");

여기서, \uD83D,\uDE91surrogate pairs라고 불린다. surrogate pair는 두개의 유니코드가 순서대로 쓰여 한개의 다른 문자를 표현할 때, 그 2개의 유니코드를 지칭하는 용어이다.

ES6 에서는, surrogate pairs를 사용하지 않고 표현할 수 있다.

console.log("\u{1F691}");

이 문자열의 길이는 여전히 2다.

The codePointAt(index)


codePointAt() 메서드는 인수의 인덱스에 해당하는 문자의 코드포인트(양의 정수)를 반환한다.

console.log("\uD83D\uDE91".codePointAt(1)); // 56977
console.log("\u{1F691}".codePointAt(1)); // 56977
console.log("hello".codePointAt(2)); // 108
console.log("hello".codePointAt(3)); // 108

String.fromCodePoint(number1, ...,number2)


fromCodePoint() 메서드는 String 객체의 메서드로, 이는 코드포인트 순서를 인수로받아 문자열을 반환한다.

console.log(String.fromCodePoint(0x61, 0x62, 0x63)); // abc
console.log("\u0061\u0062 " == String.fromCodePoint(0x61, 0x62)); // true

repeat(count)


repeat() 메서드는 새로운 문자열을 construct하고 반환하는데, 말그대로 인수의 숫자만큼 반복한다.

console.log("a".repeat(6)); // "aaaaaa"

includes(string,index)


includes() 메서드는 인수의 문자열이 존재하는지 여부를 불린 값으로 반환한다. 두번 째 인수는 optional 하며, 서칭을 시작하는 시작 위치가 된다. 디폴트로는 0이다.

startsWith(string,index)


startsWith() 메서드는 인수로 받은 문자열로 시작하는지의 여부를 불린값으로 반환한다.

var str = "Hi, I am a JS Developer";
console.log(str.startsWith('Hi, I am')); // true

두번 째 인수는 서칭을 시작하는 위치다.

endsWith(string,index)


endsWith()는 인수로 받은 문자열로 끝나는지 여부를 불린 값으로 반환한다. 두번 째 값은 end 위치를 정한다.

Normalization


Normalization은 문자열의 의미를 바꾸지 않은 상태로 코드포인트를 서칭하거나 표준화 하는 과정이다. 유니코드 문자열 normalization 과정을 예시로 보자.

case Study


16비트로 저장될 수 있거나, surrogate pair로 표현될 수 있는 수많은 유니코드 문자가 존재한다. 예시를 보자.

console.log("\u00E9"); //output 'é'
console.log("e\u0301"); //output 'é'

문제는 == 오퍼레이터를 적용할 때 발생하는데, 이터레이팅이나 길이를 구할 때 예상치 못한 결과를 얻게 된다.

var a = "\u00E9";
var b = "e\u0301";
console.log(a == b);
console.log(a.length);
console.log(b.length);
for(let i = 0; i<a.length; i++)
{
 console.log(a[i]);
}
for(let i = 0; i<b.length; i++)
{
 console.log(b[i]);
}

// Output
false
1
2
é
é

a,b 모두 같은 문자열을 나타내지만, 연산이나 메서드를 사용하게 되면 다른 결과를 나타낸다.

length 프로퍼티는 surrogate pairs를 무시하며, 모든 16비트를 한개의 문자로 취급한다. == 연산자는 바이너리 비트를 매치하며 따라서 이 또한 surrogate pairs를 무시한다. [] 오퍼레이터 역시 모든 16비트를 인덱스로 취급하기에 surrogate pairs를 무시한다.

이러한 문제를 해결하기 위해서, 우리는 surrogate pairs를 16비트 문자표현으로 바꿔줘야 한다. 이 과정을 normalization이라고 한다.

ES6에서는 normalize() 함수를 지원한다.

var a = "\u00E9".normalize();
var b = "e\u0301".normalize();
console.log(a == b);
console.log(a.length);
console.log(b.length);
for(let i = 0; i<a.length; i++)
{
 console.log(a[i]);
}
for(let i = 0; i<b.length; i++)
{
 console.log(b[i]);
}

// Output
true
1
1
é
é

Template strings


Template Strings는 문자열을 생성하는 새로운 방식이고, 이는 여러가지 일들을 수월하게 만들어준다. 표현식 삽입, 멀티라인, 문자열 포매팅, 태깅 등 많은 것을 사용할 수 있다. 이 템플릿 문자열은 항상 런타임에서 기본 자바스크립트의 문자열로 변환되며 따라서 이는 우리가 일반 문자열을 사용하는 어디에도 사용 가능하다.

let str1 = `hello!!!`; //template string
let str2 = "hello!!!";
console.log(str1 === str2); //output "true"

Expressions


ES5에서 문자열에 표현식을 삽입하기 위해서는 다음과 같은 방식을 사용했다.

var a = 20;
var b = 10;
var c = "JavaScript";
var str = "My age is " + (a + b) + " and I love " + c;
console.log(str);
// My age is 30 and I love JavaScript

ES6에서는 아주 간단하게 해결된다. ${expressions}의 형태로 쓰이며, 여기에서 사용된 표현식은 템플릿 문자열을 일반 문자열로 변환시키는 함수에 전달된다. 디폴트 함수는 그냥 concatenate해주지만, 우리가 함수를 커스터마이징하면 이를 tagged template string이라고 부르며, 커스텀 함수를 tag function이라고 부른다.

let a = 20;
let b = 10;
let c = "JavaScript";
letstr = `My age is ${a+b} and I love ${c}`;
console.log(str);
// My age is 30 and I love JavaScript

tag template string


tagged template string을 만들어보자. 기존의 디폴트 함수와 똑같은 역할을 하는 tag function을 구현해보자.

let tag = function (strings, ...values) {
    let result = "";
    for (let i = 0; i < strings.length; i++) {
        result += strings[i];
        if (i < values.length) {
            result += values[i];
        }
    }
    return result;
};

return result;

};
let a = 20;
let b = 10;
let c = "JavaScript";
let str = tag `My age is ${a+b} and I love ${c}`;
console.log(str);

// My age is 30 and I love JavaScript

tag 의 인수로 들어가는 string은 템플릿 문자열의 문자열들이며, values${expression}의 값들의 배열이다.

Multiline Strings


ES5에서는 멀티라인 텍스트를 작성하기 위해서는 다음과 같이 작성해야 했다.

console.log("1\n2\n3");
// output
1
2
3

ES6에서는 템플릿 문자열을 이용하면 아주 간단하게 할 수 있다.

console.log(`1
2
3`);

// output
1
2
3

Raw strings


raw string이란, 이스케이프된 문자가 인터프리트 되지 않은 일반 문자열을 의미한다.

우리는 템플릿문자열을 통하여 raw string을 생성할 수 있다. String.raw 라는 tag function을 사용한다.

let s = String.raw `xy\n${ 1 + 1 }z`;
console.log(s);

// xy\n2z

여기서의 결과값은 인터프리트가 되지 않았으므로 6의 length 를 가진다.

profile
연세대학교 산업공학과 웹개발 JavaScript

0개의 댓글