ECMAScript 2015 S67
1. Primitive
JS는 다음의 값을 거짓으로 처리(따라서 거짓이 아니면 참)
"", 0, false, undefined, null, NaN
Boolean
문제점
1. C스타일(false가 없고 0을 사용하는)을 뛰어넘어 다양한 편법으로 상태를 검사하는 코드가 난무하게 됨
function(){
if(arguments.length) ...
function(v){
if(v.trim()) ...
2. 가부 판정을 위한 메소드의 부재로 숫자나 문자열을 false대용으로 사용
if(str.indexOf(token) > -1) ...
if(i = str.indexOf(token), i > -1) v = str.substring(0, i);
true, false의 용도를 정확히 하고 자주 쓰는 판정에 대한 Boolean 메소드 제공
Boolean
if(v === parseInt(v, 10)) ...
if(Number.isInteger(v)) ...
if(v === v + 1 || v === v - 1) ...
if(Number.isFinite(v))...
str = 'abcd';
if(str.indexOf('c') > -1) ...
if(str.include('c')) ...
if(str.substr(0, 3) === 'abc') ...
if(str.startsWith('abc')) ...
if(str.substr(str.length - 3) === 'bcd') ...
if(str.endsWith('bcd')) ...
Array.prototype.include = function(v){
return this.indexOf(v) > -1;
};
애매한 부정값으로 사용되므로 값이 없음을 나타내도록 언어의 여러 요소에서 강제하여 제한된 용도로 사용하게 유도함
undefined
let [a, b = 3] = [1];
console.log(b); //3
let [a, b = 3] = [1, undefined];
console.log(b); //3
const test = function(a, b = 3){
return a + b;
};
console.log(test(1)); //4
console.log(test(1, undefined)); //4
ECMAScript 2015 S67
2. Implicit System
어떠한 코드 상의 힌트도 없고, 단지 언어스펙을 외운 사람만 의미가 파악됨.
또한 언어에 정의된 키워드가 아니므로 오용할 수 있음.
arguments
const test = function(){
let arguments = 3;
console.log(arguments);
}
test(5,6,7) //3
const test = function(...arg){
console.log(arg);
};
코드에서 인식할 수 있는 명확한 표현으로 변경
자동 형변환 등 엔진의 내재된 작동에 사용자가 작성한 객체가 반응하게 하려면
어떠한 코드 상의 힌트도 없고, 단지 언어스펙을 외운 사람만 의미가 파악됨.
Symbol
let a = {
toString:_=>'a',
valueOf:_=>1,
toJSON:=>'{a:1}'
};
let a = {
[Symbol.toPrimitive]:hint=>hint == 'string' ? 'a' : 1
};
코드에서 인식할 수 있는 명확한 표현으로 변경
toString, valueOf, toJSON 등은 일반문자열이므로
이것이 엔진 작동에 반응하는 트리거 메소드라는 것을
코드로 알 방법은 없고
언어스펙을 외운 사람만 의미가 파악됨.
코드 상으로 시스템요구사항에 맞는 트리거 메소드임을 이해할 수 있음.
ECMAScript 2015 S67
3. Iteration
for, while 등 문으로 구성된 반복은 실행될 수 있으나 값으로 존재할 수 없음.
Iterable & Iterator
1. 사전에 정의가 끝난 정적 값에 대한 반복만 처리가능
2. 반드시 반복전에 반복할 대상에 대한 사전처리가 완료되어있어야 함.
3. 반복처리될 대상에 대한 지연처리가 불가
인자로 전달하거나 상태를 기억해 둘 수 없음
표준적인 값형태의 반복처리기가 필요.
1. 수식적이거나 알고리즘을 통해서 계산될 값은 미리 정의해둘 이유가 없음
2. 메모리에 정의한적이 없어도 반복시점에 자원을 확보하여 반환할 수도 있음
지연실행의 필요성
반복이란 매 반복시 마다 실행될 부분과 계속 반복할지 여부로 구성됨
Iterable & Iterator
while(계속 반복할지 여부){
반복시마다 실행될 부분
}
1. 반복시마다 실행될 부분 → next()메소드를 호출함
2. 계속 반복할지 여부 → next로 반환된 객체의 done키에 있는 boolean값
Iterator Protocol
let [a, b, c] = 'abc';
let a = [...'abc'];
const test = (...arg)=>arg.join('-');
test(...'abcd'); //'a-b-c-d'
문자열은 Iterable(Iterator를 반환함)
Iterable & Iterator
let n2 = {
[Symbol.iterator](){
var cursor = -1, max = 10;
return {
done:false, value:0,
next(){
if(cursor++ <= max){
this.value = cursor * cursor;
}else{
this.value = undefined;
this.done = true;
}
return this;
}
};
}
};
((...a)=>console.log(a))(...n2); //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
커스텀 Iterable
Iterable을 직접 제작하는 것은 상당한 반복작업을 유발하므로 언어차원에서 간략한 문법을 제공함.
generator
const gene = function*(max){
let cursor = -1;
while(cursor++ < max) yield cursor * cursor;
};
((...a)=>console.log(a))(...gene(10)); //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1. 객체 컨텍스트를 변수 컨텍스트로
2. 제어문을 중지시킬 수 있는 yield
실행중인 EC에 대해 suspend를 걸 수 있는 기능을 엔진차원에서 추가
ECMAScript 2015 S67
4. Class
결국 OOP는 여전히 가장 주요한 아키텍쳐방법론임. 프로토타입을 통해 대체가능성과 내적동질성을 확보할 수는 있음.
Class
var Dog = function(){};
Dog.prototype.bark = function(){
return 'woof';
};
var Spitz = function(){};
Spitz.prototype = new Dog();
Spitz.prototype.bark = function(){
return 'woof woof'; //더 시끄러움.
};
var dog = new Spitz();
console.log(dog instanceof Dog); //true 대체가능성
console.log(dog.bark()); //woof woof 내적동질성
중복키의 문제
1. 프로토타입은 단일 체이닝 구조로 대상객체가 상위객체의 키를 가리도록 되어있음.
2. 따라서 반드시 하위클래스는 상위의 이름을 피해서 제작해야만 상위구조와 상호작용할 수 있음.
Class
var Parent = function(){};
Parent.prototype.test = function(){return 'parent';};
var Child = fuction(){};
Child.prototype = new Parent();
Child.prototype.test = function(){return 'child';};
var child = new Child();
child.test(); //child
생성자에서도 제네릭화된 로직을 짤 수 없고 반드시 하드코딩된 클래스 이름을 알아야만 생성자 체인을 시킬 수 있음.
var Parent = function(a){
this.a = a
};
var Child = fuction(a, b){
Parent.call(this, a);
this.b = b;
};
새로운 컨텍스트 객체 도입
1. 기존 this가 현재 주체가 되는 객체의 참조로서 동작하는 컨텍스트를 제공했다면,
2. super는 상위클래스에 대한 상대경로를 제공하는 새로운 컨텍스트를 제공함.
단 사용되는 곳에 따라 의미가 달라짐.
Class
const Parent = class{
constructor(a){
this.a = a;
}
}
const Child = class extends Parent{
constructor(a, b){
super(a); //Parent.call(this, a); 에 해당됨
this.b = b;
}
}
생성자에서 사용되는 경우
Class
const Parent = class{
test(){
return 'parent';
}
};
const Child = class extends Parent{
test(){
const v = super.test(); //Parent.prototype.test.call(this) 에 해당
return v + ':child'
}
};
메소드에서 사용되는 경우
그 외에도
1. 생성자를 일반 함수로 호출하려하거나
2. 메소드를 생성자로 사용하려 하는 등의 오용되는 문제에 대해
예외를 발생시켜 방어하도록 설계됨.

[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive

  • 1.
  • 2.
    JS는 다음의 값을거짓으로 처리(따라서 거짓이 아니면 참) "", 0, false, undefined, null, NaN Boolean 문제점 1. C스타일(false가 없고 0을 사용하는)을 뛰어넘어 다양한 편법으로 상태를 검사하는 코드가 난무하게 됨 function(){ if(arguments.length) ... function(v){ if(v.trim()) ... 2. 가부 판정을 위한 메소드의 부재로 숫자나 문자열을 false대용으로 사용 if(str.indexOf(token) > -1) ... if(i = str.indexOf(token), i > -1) v = str.substring(0, i);
  • 3.
    true, false의 용도를정확히 하고 자주 쓰는 판정에 대한 Boolean 메소드 제공 Boolean if(v === parseInt(v, 10)) ... if(Number.isInteger(v)) ... if(v === v + 1 || v === v - 1) ... if(Number.isFinite(v))... str = 'abcd'; if(str.indexOf('c') > -1) ... if(str.include('c')) ... if(str.substr(0, 3) === 'abc') ... if(str.startsWith('abc')) ... if(str.substr(str.length - 3) === 'bcd') ... if(str.endsWith('bcd')) ... Array.prototype.include = function(v){ return this.indexOf(v) > -1; };
  • 4.
    애매한 부정값으로 사용되므로값이 없음을 나타내도록 언어의 여러 요소에서 강제하여 제한된 용도로 사용하게 유도함 undefined let [a, b = 3] = [1]; console.log(b); //3 let [a, b = 3] = [1, undefined]; console.log(b); //3 const test = function(a, b = 3){ return a + b; }; console.log(test(1)); //4 console.log(test(1, undefined)); //4
  • 5.
    ECMAScript 2015 S67 2.Implicit System
  • 6.
    어떠한 코드 상의힌트도 없고, 단지 언어스펙을 외운 사람만 의미가 파악됨. 또한 언어에 정의된 키워드가 아니므로 오용할 수 있음. arguments const test = function(){ let arguments = 3; console.log(arguments); } test(5,6,7) //3 const test = function(...arg){ console.log(arg); }; 코드에서 인식할 수 있는 명확한 표현으로 변경
  • 7.
    자동 형변환 등엔진의 내재된 작동에 사용자가 작성한 객체가 반응하게 하려면 어떠한 코드 상의 힌트도 없고, 단지 언어스펙을 외운 사람만 의미가 파악됨. Symbol let a = { toString:_=>'a', valueOf:_=>1, toJSON:=>'{a:1}' }; let a = { [Symbol.toPrimitive]:hint=>hint == 'string' ? 'a' : 1 }; 코드에서 인식할 수 있는 명확한 표현으로 변경 toString, valueOf, toJSON 등은 일반문자열이므로 이것이 엔진 작동에 반응하는 트리거 메소드라는 것을 코드로 알 방법은 없고 언어스펙을 외운 사람만 의미가 파악됨. 코드 상으로 시스템요구사항에 맞는 트리거 메소드임을 이해할 수 있음.
  • 8.
  • 9.
    for, while 등문으로 구성된 반복은 실행될 수 있으나 값으로 존재할 수 없음. Iterable & Iterator 1. 사전에 정의가 끝난 정적 값에 대한 반복만 처리가능 2. 반드시 반복전에 반복할 대상에 대한 사전처리가 완료되어있어야 함. 3. 반복처리될 대상에 대한 지연처리가 불가 인자로 전달하거나 상태를 기억해 둘 수 없음 표준적인 값형태의 반복처리기가 필요. 1. 수식적이거나 알고리즘을 통해서 계산될 값은 미리 정의해둘 이유가 없음 2. 메모리에 정의한적이 없어도 반복시점에 자원을 확보하여 반환할 수도 있음 지연실행의 필요성
  • 10.
    반복이란 매 반복시마다 실행될 부분과 계속 반복할지 여부로 구성됨 Iterable & Iterator while(계속 반복할지 여부){ 반복시마다 실행될 부분 } 1. 반복시마다 실행될 부분 → next()메소드를 호출함 2. 계속 반복할지 여부 → next로 반환된 객체의 done키에 있는 boolean값 Iterator Protocol let [a, b, c] = 'abc'; let a = [...'abc']; const test = (...arg)=>arg.join('-'); test(...'abcd'); //'a-b-c-d' 문자열은 Iterable(Iterator를 반환함)
  • 11.
    Iterable & Iterator letn2 = { [Symbol.iterator](){ var cursor = -1, max = 10; return { done:false, value:0, next(){ if(cursor++ <= max){ this.value = cursor * cursor; }else{ this.value = undefined; this.done = true; } return this; } }; } }; ((...a)=>console.log(a))(...n2); //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 커스텀 Iterable
  • 12.
    Iterable을 직접 제작하는것은 상당한 반복작업을 유발하므로 언어차원에서 간략한 문법을 제공함. generator const gene = function*(max){ let cursor = -1; while(cursor++ < max) yield cursor * cursor; }; ((...a)=>console.log(a))(...gene(10)); //[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 1. 객체 컨텍스트를 변수 컨텍스트로 2. 제어문을 중지시킬 수 있는 yield 실행중인 EC에 대해 suspend를 걸 수 있는 기능을 엔진차원에서 추가
  • 13.
  • 14.
    결국 OOP는 여전히가장 주요한 아키텍쳐방법론임. 프로토타입을 통해 대체가능성과 내적동질성을 확보할 수는 있음. Class var Dog = function(){}; Dog.prototype.bark = function(){ return 'woof'; }; var Spitz = function(){}; Spitz.prototype = new Dog(); Spitz.prototype.bark = function(){ return 'woof woof'; //더 시끄러움. }; var dog = new Spitz(); console.log(dog instanceof Dog); //true 대체가능성 console.log(dog.bark()); //woof woof 내적동질성
  • 15.
    중복키의 문제 1. 프로토타입은단일 체이닝 구조로 대상객체가 상위객체의 키를 가리도록 되어있음. 2. 따라서 반드시 하위클래스는 상위의 이름을 피해서 제작해야만 상위구조와 상호작용할 수 있음. Class var Parent = function(){}; Parent.prototype.test = function(){return 'parent';}; var Child = fuction(){}; Child.prototype = new Parent(); Child.prototype.test = function(){return 'child';}; var child = new Child(); child.test(); //child 생성자에서도 제네릭화된 로직을 짤 수 없고 반드시 하드코딩된 클래스 이름을 알아야만 생성자 체인을 시킬 수 있음. var Parent = function(a){ this.a = a }; var Child = fuction(a, b){ Parent.call(this, a); this.b = b; };
  • 16.
    새로운 컨텍스트 객체도입 1. 기존 this가 현재 주체가 되는 객체의 참조로서 동작하는 컨텍스트를 제공했다면, 2. super는 상위클래스에 대한 상대경로를 제공하는 새로운 컨텍스트를 제공함. 단 사용되는 곳에 따라 의미가 달라짐. Class const Parent = class{ constructor(a){ this.a = a; } } const Child = class extends Parent{ constructor(a, b){ super(a); //Parent.call(this, a); 에 해당됨 this.b = b; } } 생성자에서 사용되는 경우
  • 17.
    Class const Parent =class{ test(){ return 'parent'; } }; const Child = class extends Parent{ test(){ const v = super.test(); //Parent.prototype.test.call(this) 에 해당 return v + ':child' } }; 메소드에서 사용되는 경우 그 외에도 1. 생성자를 일반 함수로 호출하려하거나 2. 메소드를 생성자로 사용하려 하는 등의 오용되는 문제에 대해 예외를 발생시켜 방어하도록 설계됨.