javaScript/js.functionInES6

ES6 함수의 추가 기능

  1. 함수의 구분
  • ES6 이전의 함수는 동일한 함수라도 다양한 형태로 호출할 수 있다.

  • ES6 이전의 함수는 callable이며 constructor 이다.

    • callable - 호출할 수 있는 함수 객체
    • constructor - 인스턴스를 생성할 수 있는 함수 객체
    • non-constructor - 인스턴스를 생성할 수 없는 함수 객체
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      var foo = function () {
      return 1;
      };

      // 일반적인 함수로서 호출
      foo (); // 1

      // 생성자 함수로서 호출
      new foo (); // foo {}

      // 메소드로서 호출
      var obj = { a: foo };
      obj.a(); // 1
  • 일반적으로 메소드라고 부르는 객체에 바인딩된 함수도 callable이며 constructor이다.

  • 객체에 바인딩된 함수도 일반 함수, 생성자 함수로서 호출할 수도 있다.

  • 바인딩된 함수가 constructor면 prototype 프로퍼티에 바인딩된 프로토타입 객체를 생성한다는 것을 의미

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var obj = {
    x: 10;
    f: function () {
    return this.x;
    }
    };
    //프로퍼티 f에 할당된 함수를 메소드로서 호출
    console.log(obj.f()); // 10
    //프로퍼티 f에 할당된 함수를 일반 함수로서 호출
    var bar = obj.f;
    console.log(bar()); // undifined
    //프로퍼티 f에 할당된 함수를 생성자 함수로서 호출
    console.log(new obj.f()); // f {}
  • ES6 이전의 모든 함수는 사용 목적에 따라 명확한 구분이 없음

  • 호출 방식에 특별한 제약 없음

  • 생성자 함수로 호출되지 않아도 프로토타입 객체를 생성

  • ES6에서는 사용 목적에 따라 함수를 3가지 종류로 명확히 구분함

ES함수의 구분 cosntructor prototype super arguments
일반 함수 O O x O
메소드 X X O O
화살표 함수 X X X X

2. 메소드

  • ES6 사양에서 메소드는 메소드 축약 표현으로 정의된 함수 만을 의미한다.

  • 인스턴스를 생성할 수 없는 non-constructor, (생성자 함수로서 호출 불가)

  • prototype 프로퍼티가 없고 프로토타입도 생성하지 않는다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const obj = {
    x: 1,
    foo () { // 메소드
    return this.x;
    },
    bar: function () {
    return this.x // 일반함수 바인딩
    }
    };
    console.log(obj()); // 1
    console.log(bar()); // 1

    new obj.foo(); // TypeError: obj.foo is not a constructor
    new obj.bar(); // bar {} 일반함수여서 호출가능

    Object.prototype.hasOwnProperty.call(obj.foo, 'prototype'); // false
  • 표준 빌트인 객체의 메소드는 모두 non-constructor

  • ES6 메소드는 메소드가 바인딩된 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다.
    super 참조는 [[HomeObject]]를 사용하여 수퍼 클래스의 메소드를 참조하므로 내부슬롯을 갖는 ES6 메소드만이 super 키워드를 사용할 수 있다.

  • ES6 메소드가 아니면 super 키워드를 사용할 수 없다. (내부슬롯 안가지고있음)
    일반 함수로 super 키워드를 사용했을 시 SytaxError

  • super 기능 추가, constructor 제거.

  • 메소드 정의할 때, 프로퍼티 값으로 익명 함수 표현식을 할당하는 ES6 이전 방식은 더이상 사용 하지 말아야 함.

3. 화살표 함수

3.1 화살표 함수 정의

(1) 매개변수 선언
  • 매개 변수가 여러 개인 경우, 소괄호 안에 매개 변수를 선언한다.
  • 매개 변수가 한 개인 경우, 소괄호 생략할 수 있다.
  • 매개 변수가 없는 경우, 소괄호를 생략할 수 없다.
(2) 함수 몸체 정의
  • 함수 몸체가 한 줄의 문으로 구성된다면 함수 몸체를 감싸는 중괄호 생략 가능
    이때 문은 암묵적으로 반환된다.

  • 여러 줄의 문으로 구성된다면 중괄호 생략 불가능, 반환값이 있다면 명시적으로 반환해야한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    x => x * x;
    x => { return x + x; }

    // 화살표 함수와 일반함수 비교

    const now = () => Date.now();

    var now () {
    return Date.now();
    }
    //
    const x = value => value;

    var x = function(value) {
    return value;
    };
    //
    const sum = (a, b) => a + b;

    var sum = function(a, b) {
    return a + b;
    }
  • 객체 리터럴을 반환하는 경우, 객체 리터럴을 소괄호()로 감싸 주어야 한다.

    1
    2
    3
    4
    5
    6
    7
    8
    () => { return { a: 1 }; }
    () => ({ a: 1}) //같은 표현

    const create = (id, content) => ({ id, content });

    var create = function (id, content) {
    return { id, content };
    };
  • 화살표 함수도 즉시 실행 함수(IIFE)로 사용 가능

    1
    2
    3
    4
    5
    const person = (name => ({
    sayHi() { return `My name is ${name}`;}
    }))('jung');

    console.log(person.sayHi());
  • 화살표 함수도 일급 객체.. 따라서 고차함수(HOF)에 인수로 전달할 수 있다.
    (Array.prototype.map/filter/reduce)

    1
    2
    3
    4
    5
    6
    // ES6 
    [1, 2, 3].map( v => v * 2); // [2, 4, 6]
    // ES5
    [1, 2, 3].map(function (v) {
    return v * 2;
    });

3.2 화살표 함수와 일반 함수의 차이

(1) 화살표 함수는 non-constructor (인스턴스 생성X)
  • 생성자 함수로 호출할 수 없다. (TypeError)
  • prototype 프로퍼티가 없고 프로토타입도 생성하지 않는다.
(2) 중복된 매개 변수 이름을 선언할 수 없다.
  • 일반 함수는 중복된 매개 변수를 선언해도 에러가 발생하지 않는다.(SytaxError)
(3) 화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.
  • 화살표 함수 내에서 참조하면 스코프 체인을 통해 상위 컨텍스트의 것을 참조한다.

3.3 this

  • 중첩 함수 내부의 this가 외부 함수의 this와 다르기 때문에 발생하는 문제를 해결하기 위해.
  • 화살표 함수는 함수 자체의 this 바인딩이 없다. 화살표 함수 내부에서 this를 참조하면 상위 컨텍스트의 this를 그대로 참조한다. 이를 Lexical this라 한다.

화살표 함수의 this가 함수가 정의된 위치에 의해 결정된다는 것을의미..

  • 화살표 함수가 화살표 함수의 중첩 함수인 경우, 부모 화살표 함수가 참조하는 상위 컨텍스트의 this를 참조한다. 화살표 함수가 전역 함수라면 this는 전역 객체를 가리킴

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const foo = () => console.log(this);
    foo(); //window

    (function () {
    const foo = () => console.log(this);
    foo();
    }).call({ a: 1}); // { a: 1}
    //foo의 상위 컨텍스트는 즉시 실행함수. this는 즉시 실행함수를 가리킴

    const counter = {
    num: 1;
    increase: () => ++this.num
    };
    console.log(counter.increase()); //NaN
    // 상위 컨텍스트는 전역이므로 this는 전역 객체를 가리킴
  • 화살표 함수 내부의 this는 Function.prototype.call/apply/bind 메소드를 사용하여 변경할 수 없다. 화살표 함수의 this는 일단 결정된 이후 변경할 수 없고 언제나 유지된다.

  • 메소드를 화살표 함수로 정의하는 것은 자제해야 한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const person = {
    name: 'jung'
    sayHi: () => console.log(`hi ${this.name}`)
    };
    person.sayHi(); // hi
    //전역 객체 window에 빌트인 프로퍼티 name이 존재
    //함수 내부의 this는 전역 객체를 가리키므로 브라우저에서 실행하면 빈문자열을 갖는
    // window.name이 출력된다.
    //
    // ES6 메소드 정의를 사용하기
    const person = {
    name: 'jung',
    sayHi() {
    console.log(`hi ${this.name}`);
    }
    };
    person.sayHi() //hi jung
  • 프로토타입 객체에 화살표 함수를 할당하는 경우도 동일한 문제가 발생한다.(위 예제와)

  • 프로토타입 객체에는 ES6 메소드 정의를 사용할 수 없으므로 일반 함수를 할당한다.

  • 클래스 필드 정의 제안을 사용하여 클래스 필드에 화살표 함수를 할당할 수도있다.

  • 클래스 필드에 할당한 화살표 함수는 프로토타입 메소드가 아니라 인스턴스의 메소드가 된다.
    ES6 메소드 정의를 사용하는 것이 좋다.

    1
    2
    3
    4
    5
    6
    7
    class Person {
    name = 'jung';

    sayHi() { console.log(`hi ${this.name}`); }
    }
    const person = new Person();
    person.sayHi(); //hi jung

    3.4 super

  • 화살표 함수는 함수 자체에 super 바인딩이 없다.

  • 화살표 함수 내부에서 super를 참조하면 상위 컨텍스트의 super를 참조한다.

  • super 내부슬롯 [[HomeObject]]를 갖는 ES6 메소드만이 사용할 수 있는 키워드

3.5 arguments

  • 화살표 함수는 함수 자체의 arguments 바인딩이 없다.
  • 함수 내부에서 arguments를 참조하면 상위 컨텍스트의 argumnets를 참조한다.
  • 상위 컨텍스트의 arguments 객체를 참조할 수는 있지만 화살표 함수 자신에게 전달된 인수 목록을 확인할 수 없으므로 도움이 되지 않음
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    (function () {
    const foo = () => console.log(arguments); //[Arguments] { '0': 1, '1' : 2}
    foo(3, 4);
    }(1 ,2));
    // 화살표 함수 foo의 arguments는 즉시 실행 함수의 arguments를 가리킨다.
    // 중첩 함수 foo의 상위 컨텍스트가 즉시 실행함수..
    //
    const bar = () => console.log(arguments);
    bar(1 ,2); // ReferenceError
    // 전역 함수 bar의 상위 컨텍스트는 전역, 전역에는 arguments 객체가 없다.
    //(함수 내에서만 유효)

4 Rest 파라미터

4.1 기본 문법

Rest 파라미터(나머지 매개변수)는 매개변수 이름 앞에 세개의 점을 붙여서 정의한 매개변수를 의미한다. 함수에 전달된 인수들의 목록을 배열로 전달받는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
function foo (...rest) {
console.log(rest); [1, 2, 3, 4, 5]
console.log(Array.isArray(rest)); // true
}
foo(1, 2, 3, 4, 5);

// 함수에 전달된 인수들은 순차적으로 파라미터와 Rest 파라미터에 할당된다.
function bar (param1, param2, ...rest) {
console.log(param1); // 1
console.log(param2); // 2
console.log(rest); // [ 3, 4, 5 ]
}
bar (1, 2, 3, 4, 5);
  • Rest 파라미터는 반드시 마지막 파라미터여야한다. (SyntaxError)
  • Rest 파라미터는 단 하나만 선언할 수 있다.
  • 함수 객체의 length 프로퍼티에 영향을 주지 않는다.

4.2 Rest 파라미터와 arguments 객체

  • ES5에서는 가변 인자 함수의 경우, arguments 객체를 통해 인수를 확인한다.
    arguments 객체는 유사 배열 객체이며 함수내부에서 지역 변수처럼 사용할 수 있다.

  • 가변 인자 함수는 파라미터를 통해 인수를 전달받는 것이 불가능하므로 arguments 객체를 활용하여 인수를 전달받는다.

  • arguments 객체는 유사 배열 객체이므로 배열 메소드를 사용하려면 Function.prototype.call 메소드를 통해 this를 변경하여 배열 메소드를 호출해야함

  • ES6에서는 rest 파라미터를 사용하여 가변인자의 목록을 배열로 직접 전달받을 수 있다.

  • 유사 배열인 arguments 객체를 배열로 변환하는 번거로움을 피할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sum() {
var array = Array.prototype.slice.call(arguments);
//유사 배열 객체인 argments 객체를 배열로 변환한다.
return array.reduce(function (pre, cur) {
return pre + cur;
});
}
console.log(sum(1, 2, 3, 4, 5)); //15 ?

//ES6
function sum(...args) {
return args.reduce((pre, cur) => pre + cur);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
  • 화살표 함수는 함수 자체의 arguments 객체를 갖지 않는다. 화살표 함수로 가변인자 함수를 구현해야 할 때는 반드시 rest 파라미터를 사용해야 한다.

5. 매개변수 기본값

  • 매개변수에 적절한 인수가 전달되었는지 함수 내부에서 확인할 필요가 있다.
    방어 코드가 필요.
  • ES6에서는 매개변수 기본값을 사용하여 함수 내에서 수행하던 인수 체크, 초키화를 간소화할 수 있다.
  • 매개변수 기본값은 매개변수에 인수를 전달하지 않았을 경우와 undifined를 전달한 경우에만 유효하다.
  • Rest 파라미터에는 기본값을 지정할 수 없다. (SyntaxError)
  • 매개변수의 기본값은 함수 객체의 length 프로퍼티와 argument 객체에 영향을 주지않는다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    function sum (x, y) {
    x = x || 0;
    y = y || 0;

    return x + y;
    }
    console.log(sum(1, 2)); //3
    console.log(sum(1)); //1
    //

    function sum (x = 0, y = 0) {
    return x + y;
    }
    //
    function logName (name = 'jung') {
    console.log(name);
    }
    logName(); //jung
    logName(undifined); //jung
    logName(null); //null

    //
    function sum(x, y = 0) {
    console.log(arguments);
    }
    console.log(sum.length); //1? 2 아닌가?

    sum(1); // Arguments { '0': 1 }
    sum(1, 2); // Arguments { '0' : 1, '1' : 2}
You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×