Recent Posts
Recent Comments
Link
12-04 00:16
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

javascript ECMAScript 6부터 추가된 함수와 객체의 기능 본문

DEV&OPS/Javascript

javascript ECMAScript 6부터 추가된 함수와 객체의 기능

ALEPH.GEM 2022. 2. 21. 17:02

화살표 함수 표현식

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}
  1. 제너레이터는 호출해도 바로 실행되지 않고 이터레이터를 리턴합니다.
  2.  next() 메서드가 호출되면 첫 번째 yield expression의 위치까지 실행하여 이터레이터 result object를 리턴합니다. 이때 이터레이터 리절트 객체는 value에 yield expression 결과를, done에 완료 여부를 담은 객체입니다.
  3. 다시 next() 메서드가 호출되면 두 번째 yield 까지 실행하여 마찬가지 이터레이터 리절트 객체를 리턴합니다.
  4. 다시 next() 메서드가 호출되면 세 번째 yield 까지 실행하여 마찬가지 이터레이터 리절트 객체를 리턴합니다.
  5. 마지막에서는 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&#039;").replace(/"/g, "&quot;").replace(/`/g, "&#096;");
            }
        }
        var userinput = "<scrip> alert('test');";
        var message = htmlEscape`<p>${userinput}</p>`;  /* <p>&lt;scrip&gt; alert(&#039;test&#039;);</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

 

 

 

 

728x90

'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