삶 가운데 남긴 기록 AACII.TISTORY.COM
javascript ECMAScript 6부터 추가된 함수와 객체의 기능 본문
화살표 함수 표현식
var square = function(x){ return x*x; };
//화살표 함수 표현식
var square = (x) => { return x*x; };
//인수가 한개이면 인수를 묶는 괄호를 생략할 수 있습니다.
var square = x => { return x*x; };
//인수가 없는 경우
var f = () => { return alert("x"); };
//함수 몸통이 return 뿐이면 return 키워드도 생략 가능
var square = x => x*x;
//함수 몸통이 return 뿐이라도 객체를 리턴하면()으로 묶어야 함
var f = (a, b) => ({x: a, y: b});
//즉시 실행 함수
(x => x*x)(3); // 9
- this가 함수를 정의 할 때 결정됩니다.
- arguments 변수가 없습니다. 대신 아래에 나오는 나머지 매개변수를 사용할 수 있습니다.
- 생성자로 사용할 수 없습니다.
- yield 키워드(제너레이터)를 사용할 수 없습니다.
나머지 매개변수
function f(a,b, ...args){
console.log(a, b, args);
}
f(1,2,3,4,5,6); // 1 2 [3, 4, 5, 6]
인수의 기본 값
function add(a, b=a+1){
return a+b;
}
add(2); // 5
add(2, 1); // 3
이터레이터(iterator)
이터레이터는 반복 처리 가능한 객체입니다.
var a = [5,4,3];
var iter = a[Symbol.iterator]();
console.log(iter.next()); //Object {value: 5, done: false}
console.log(iter.next()); //Object {value: 4, done: false}
console.log(iter.next()); //Object {value: 3, done: false}
console.log(iter.next()); //Object {value: undefined, done: true}
console.log(iter.next()); //Object {value: undefined, done: true}
next() 메서드를 호출할 때마다 value와 done 프로퍼티를 갖는 객체를 리턴합니다.
var a = [5,4,3];
var iter = a[Symbol.iterator]();
while(true){
var iteratorResult = iter.next();
if(iteratorResult.done == true) break;
var v = iteratorResult.value;
console.log(v);
}
//5
//4
//3
위 내용을 for / of 문으로 구현할 수 있습니다.
var a = [5,4,3];
for(var v of a) console.log(v)
제너레이터
제너레이터는 function* 으로 정의하고 반복가능한 이터레이터를 리턴하는 함수입니다. 작업의 일시 정지와 재시작이 가능하며 자신의 상태를 관리합니다.
제너레이터의 매커니즘
function* gen(){
yield 1;
yield 2;
yield 3;
}
var iter = gen();
console.log(iter.next()); //Object {value:1, done: false}
console.log(iter.next()); //Object {value:2, done: false}
console.log(iter.next()); //Object {value:3, done: false}
console.log(iter.next()); //Object {value:undefined, done: true}
- 제너레이터는 호출해도 바로 실행되지 않고 이터레이터를 리턴합니다.
- next() 메서드가 호출되면 첫 번째 yield expression의 위치까지 실행하여 이터레이터 result object를 리턴합니다. 이때 이터레이터 리절트 객체는 value에 yield expression 결과를, done에 완료 여부를 담은 객체입니다.
- 다시 next() 메서드가 호출되면 두 번째 yield 까지 실행하여 마찬가지 이터레이터 리절트 객체를 리턴합니다.
- 다시 next() 메서드가 호출되면 세 번째 yield 까지 실행하여 마찬가지 이터레이터 리절트 객체를 리턴합니다.
- 마지막에서는 value는 undefined, done은 true를 리턴합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> m부터 n까지 정수를 생성하는 제너레이터 </title>
<script>
function* createNumbers(from, to){
while( from <= to) yield from++;
}
var iter = createNumbers(10, 30);
for(var v of iter) console.log(v); /* 10 부터 30까지 정수가 출력된다. */
</script>
</head>
<body>
</body>
</html>
2차원 배열 위에서 무작위로 이동하는 시뮬레이션
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> 2차원 배열 위에서 무작위 이동하는 시뮬레이션 </title>
<script>
function* randomWalk(c, x0, y0, d){
var dx = [1, 0, -1, 0], dy = [0, 1, 0, -1]; /* 이동 방향 */
var x = x0;
var y = y0;
c.strokeStyle = "red";
c.globalAlpha = 0.25;
while(true){
yield;
c.beginPath();
c.moveTo(x,y);
var dir = Math.floor(Math.random()*4); /* 0~3사이 난수 */
x += d*dx[dir];
y += d*dy[dir];
c.lineTo(x,y);
c.stroke();
}
}
window.onload = function(){
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
var iter = randomWalk(ctx, 300, 300, 4, "red");
setInterval(function(){iter.next();}, 10);
};
</script>
</head>
<body>
<canvas id="mycanvas" width="800" height="600"></canvas>
</body>
</html>
next() 메서드에 인수 값을 대입하면 제너레이터에 값을 전달할 수 있습니다.
전달한 값은 제너레이터가 일시 정지 직전의 yield 표현식의 값으로 사용됩니다.
이를 이용하면 제너레이터의 내부 상태를 외부에서 변경할 수 있습니다.
아래 예제는 true를 전달해서 피보나치 수열을 리셋할 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> 피보나치 수열 제너레이터 </title>
<script>
function* fibonacci(){
var fn1 = 0, fn2 = 1;
while(true){
var fnew = fn1 + fn2;
fn1 = fn2;
fn2 = fnew;
reset = yield fn1;
if(reset){
fn1 = 0; fn2 = 1;
}
}
}
var iter = fibonacci();
for(var i = 0; i < 10; i++){
console.log(iter.next().value); /* 피보나치 수열 55까지 출력 */
}
console.log(iter.next().value); /* 89 */
console.log(iter.next(true).value); /* 1 */
console.log(iter.next().value); /* 1 */
console.log(iter.next().value); /* 2 */
</script>
</head>
<body>
</body>
</html>
제너레이터 종료: return 메서드
function* g(){
yield 1;
yield 2;
yield 3;
}
var iter = g();
iter.next(); /* Object {value: 1, done: false} */
iter.return(10); /* Object {value: 10, done: true} */
iter.next(); /* Object {value: undefined, done: true} */
제너레이터 예외 던지기: throw 메서드
function* idMaker(){
var count = 0;
while(true){
try{
yield count++;
} catch(e) {
console.log("오류가 발생했습니다");
}
}
}
var iter = idMaker();
console.log(iter.next()); /* Object{value: 0, done: false} */
console.log(iter.next()); /* Object{value: 1, done: false} */
iter.throw(new Error("오류")); /* 오류가 발생했습니다. */
/* Object {value: 2, done: false} */
반복가능한 객체에 위임하기: yield*
function* f(){
yield "X";
yield "Y";
}
function* g(){
yield 0;
yield* [2, 4];
yield* "AB";
yield* f();
}
var iter = g();
for(var v of iter) console.log(v); //0, 2, 4, A, B, X, Y
템플릿 리터럴의 태그 함수
템플릿 리터럴 앞에 함수 이름을 적으면 템플릿 리터럴의 내용을 인수로 받는 함수를 호출할 수 있습니다.
function list() {
return arguments;
}
var t = list`a${1}b${2}c${3}`;
console.log(t); //[["a", "b", "c", ""], 1, 2, 3]
이때 list함수를 태그 함수라고 합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> 이스케이프 문자 변환</title>
<script>
function htmlEscape(strings, ...values){
var result = strings[0];
for(var i = 0; i < values.length; i++){
result += escape(values[i]) + strings[i+1];
}
return result;
function escape(s){
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'").replace(/"/g, """).replace(/`/g, "`");
}
}
var userinput = "<scrip> alert('test');";
var message = htmlEscape`<p>${userinput}</p>`; /* <p><scrip> alert('test');</p> */
console.log(message);
</script>
</head>
<body>
</body>
</html>
ECMAScript 6 추가된 객체 기능
계산된 프로퍼티 이름
대괄호로 묶은 계산식을 프로퍼티 이름으로 사용할 수 있습니다.
var prop ="name", i = 1;
var obj ={[prop + i]: "Tom" };
console.log(obj); //{name1: "Tom"}
프로퍼티 정의 약식 표기
프로퍼티 이름이 변수 이름과 같을 때 약식으로 표현 할 수 있습니다. 프로퍼티 값이 그 변수의 값이 됩니다.
var prop = 2;
var obj = {prop};
console.log(obj); //{prop: 2}
메서드 정의의 약식 표기
메서드 정의할 때 function() 키워드를 생략 할 수 있습니다.
var person = {
name: "Tom",
sayHello() {console.log("Hello " + this.name); }
};
단, 약식으로 표현했을 때, 생성자로 사용할 수 없으며 super 키워드도 사용할 수 없습니다.
제너레이터 정의의 약식 표기
프로퍼티의 값이 제너레이터 함수일 때 약식으로 표기 할 수 있습니다.
var obj = {
*range(n) {for(var i=0; i<n; i++) yield i; }
};
var itor = obj.range(10);
console.log(itor.next().value); //0
console.log(itor.next().value); //1
'DEV&OPS > Javascript' 카테고리의 다른 글
javascript object property (0) | 2022.03.02 |
---|---|
javascript prototype (0) | 2022.02.23 |
javascript 함수2 (0) | 2022.02.21 |
javascript 함수 (0) | 2022.02.21 |
javascript 브라우저 입출력 (0) | 2022.02.21 |