JS (26) - ES6 함수의 추가 기능

최조니·2022년 7월 23일
0

JavaScript

목록 보기
23/36

26.1 함수의 구분

ES6 이전까지의 자바스크립트 함수

  • 별다른 구분 없이 다양한 목적으로 사용됨

    • 일반적인 함수
    • new 연산자와 함께 호출하여 인스턴스를 생성할 수 있는 생성자 함수
    • 객체에 바인딩된 메서드
  • ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있음 ❗️

    • callable이면서 constructor
var foo = function() {
  return 1;
};

foo();			// 일반 함수 : 1

new foo();		// 생성자 함수 : foo {}

var obj = { foo: foo };
obj.foo();		// 메서드 : 1

문제점

  • 메서드라고 부르던 객체에 바인딩된 함수도 callable이며 constructor이므로, 일반 함수로서 호출할 수 있고 생성자 함수로서 호출할 수 있음
// 프로퍼티 f에 바인딩된 함수는 callable + constructor
var obj = {
  x: 10,
  f: function() { return this.x; }
};

// f에 바인딩된 함수를 메서드로서 호출
console.log(obj.f());		// 10

// f에 바인딩된 함수를 일반 함수로서 호출
var bar = obj.f;
console.log(bar());			// undefined

// f에 바인딩된 함수를 생성자 함수로서 호출
console.log(new obj.f());	// f {}
  • 사용 목적에 따라 명확한 구분이 없으므로 호출 방식에 특별한 제약이 없고 생성자 함수로 호출되지 않아도 프로토타입 객체를 생성

→ 혼란스럽고, 실수를 유발할 가능성이 있으며 성능에 좋지 않음


※ ES6에서는 함수를 사용 목적에 따라 세 가지 종류로 구분

ES6 함수 구분constructorprototypesuperarguments
일반 함수 (normal)OOXO
메서드 (method)XXOO
화살표 함수 (Arrow)XXXX
  • 일반 함수

    • ES6 이전의 함수와 차이 X
  • 메서드 / 화살표 함수

    • non-constructor

26.2 메서드

ES6에서의 메서드
: 메스드 축약 표현으로 정의된 함수만을 의미

  • ES6에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor

  • ES6 메서드는 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 프로토타입도 생성하지 않음

  • ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 가짐

    • super 참조는 내부 슬롯 [[HomeObject]]를 사용하여 수퍼클래스의 메서드를 참조하므로 내부 슬롯 [[HomeObject]]를 갖는 ES6 메서드는 super 키워드를 사용할 수 있음
    • ES6 메서드가 아닌 함수는 내부 슬롯 [[HomeObject]]를 갖지 않기 때문에 super 키워드를 사용할 수 없음
const obj = {
  x: 1,
  foo() { return this.x; },	// 메서드
  bar: function() { return this.x; }	// 일반 함수
};

console.log(obj.foo());		// 1
console.log(obj.bar());		// 1

// ES6 메서드는 인스턴스 생성 X
new obj.foo();			// TypeError: obj.foo is not a constructor
new obj.bar();			// bar {}

// ES6 메서드는 prototype 프로퍼티 X
obj.foo.hasOwnProperty('prototype');	// false
obj.bar.hasOwnProperty('prototype');	// true

26.3 화살표 함수

화살표 함수

화살표 함수
function 키워드 대신 화살표를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의하는 방법

화살표 함수 정의

  • 함수 표현식으로 정의해야 함

  • 호출 방식은 기존 함수와 동일

const multiply = (x, y) => x * y;
multiply(2, 3);		// 6

화살표 매개변수 선언

  • 매개변수가 여러 개인 경우 소괄호 안에 매개변수 선언
const multiply = (x, y) => x * y;
multiply(2, 3);		// 6
  • 매개변수가 한 개인 경우 소괄호 생략
const arrow = x => {...};
  • 매개변수가 없는 경우 소괄호 생략 X
const arrow = () => {...};

화살표 함수 몸체 정의

  • 함수 몸체가 하나의 문으로 구성된다면 함수 몸체를 감싸는 중괄호를 생략할 수 있음
    • 함수 몸체 내부의 문이 값으로 평가될 수 있는 표현식인 문이어야 함
    • 표현식이 아닌 문이라면 반환할 수 없기 때문에 에러 발생 (중괄호 생략 불가)

화살표 함수 vs 일반 함수

  • 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor

    • 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 프로토타입도 생성하지 않음
  • 중복된 매개변수 이름을 선언할 수 없음

  • 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않음

this

  • 화살표 함수는 함수 자체의 this 바인딩을 갖지 않음

    • 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조 (lexical this)
  • lexical this
    렉시컬 스코프와 같이 화살표 함수의 this가 함수가 정의된 위치에 의해 결정된다

  • 화살표 함수가 전역 함수라면 화살표 함수의 this는 전역 객체 ❗️

const foo = () => console.log(this);
foo();		// window
  • 화살표 함수는 함수 자체의 this 바인딩을 갖지 않기 때문에 Function.prototype.call, Function.prototype.apply, Function.prototype.bind를 사용해서 화살표 함수 내부의 this를 교체할 수 없음

super

  • 화살표 함수는 함수 자체의 super 바인딩을 갖지 않음
    • 화살표 함수 내부에서 super를 참조하려면 상위 스코프의 super를 참조
class Base {
  constructor(name) {
    this.name = name;
  }
  
  sayHi() {
    return `Hi! ${this.name}`;
  }
}

class Derived extends Base {
  // 화살표 함수의 super는 상위 스코프 constructor의 super
  sayHi = () => `${super.sayHi()} how are you doing?`;
}

const derived = new Derived('Lee');
console.log(derived.sayHi());

arguments

  • 화살표 함수는 함수 자체의 arguments 바인딩을 갖지 않음
    • 화살표 함수 내부에서 arguments 참조하려면 상위 스코프의 arguments를 참조
(function () {
  const foo = () => console.log(arguments);		// [Arguments] { '0': 1, '1': 2 }
  foo(3, 4);
}(1, 2));

const foo = () => console.log(arguments);
foo(1, 2);	// ReferenceError: arguments is not defined
  • 화살표 함수에서는 arguments 객체를 사용할 수 없음
    • 상위 스코프의 arguments 객체를 참조할 수 있지만, 함수 자신에게 전달된 인수 목록을 확인할 수 없고 상위 함수에게 전달된 인수 목록을 참조하므로 도움이 되지 X

26.4 Rest 파라미터

Rest 파라미터 기본 문법

Rest 파라미터 (나머지 매개변수)
: 매개변수 이름 앞에 세개의 점 ...을 붙여 정의한 매개변수

  • Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받음
function foo(...rest){
  console.log(rest);	// [1, 2, 3, 4, 5]
}

foo(1, 2, 3, 4, 5);
  • 일반 매개변수와 Rest 파라미터는 함께 사용할 수 있음 (순차적으로 할당)
    • Rest 파라미터는 반드시 마지막 파라미터여야 함❗️
    • Rest 파라미터는 단 하나만 선언할 수 있음❗️
function foo(param1, param2, ...rest){
  console.log(param1);	// 1
  console.log(param2);	// 2
  console.log(rest);	// [3, 4, 5]
}

foo(1, 2, 3, 4, 5);
// Rest 파라미터는 반드시 마지막 파라미터여야 함
function foo(...rest, param1, param2){}
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
// Rest 파라미터는 단 하나만 선언할 수 있음
function foo(...rest1, ...rest2){}
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
  • Rest 파라미터는 함수 정의 시 선언한 매개변수 개수를 나타내는 함수 객체의 length 프로퍼티에 영향을 주지 X
function foo(...rest) {}
console.log(foo.length);	// 0

function bar(x, ...rest) {}
console.log(bar.length);	// 1

function baz(x, y, ...rest) {}
console.log(baz.length);	// 2

Rest 파라미터와 arguments 객체

  • ES6 Rest 파라미터를 사용하여 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있음

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

function sum(...args) {
  return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5));	// 15
  • 함수와 ES6 메서드는 Rest 파라미터와 arguments 객체를 모두 사용할 수 있음

26.5 매개변수 기본값

  • 함수 호출 시 매개변수의 개수만큼 인수를 전달하는 것이 바람직하지만, 그렇지 않은 경우에도 에러 발생 X

    • 자바스크립트 엔진이 매개변수의 개수와 인수의 개수를 체크하지 않기 때문❗️
  • 인수가 전달되지 않은 매개변수 값은 undefined

function sum(x, y) {
  return x + y;
}

console.log(sum(1));	// NaN
  • 매개변수에 인수가 전달되었는지 확인하여 인수가 전달되지 않은 경우 매개변수에 기본값을 할당할 필요 있음 ❗️ (방어 코드 필요)
function sum(x, y) {
  x = x || 0;
  y = y || 0;
  
  return x + y;
}

console.log(sum(1, 2));		// 3
console.log(sum(1));		// 1

ES6에 도입된 매개변수 기본값

  • 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있음
function sum(x = 0, y = 0) {
  return x + y;
}

console.log(sum(1, 2));		// 3
console.log(sum(1));		// 1
  • 매개변수 기본값은 매개변수에 인수를 전달하지 않은 경우와 undefined를 전달한 경우에만 유효
function logName(name = 'Lee') {
  console.log(name);
}

logName();			// Lee
logName(undefined);	// Lee
logName(null);		// null
  • Rest 파라미터에는 기본값을 지정할 수 없음
function foo(...rest = []) {
  console.log(rest);
}	// SyntaxError: Rest parameter may not have a default initializer
  • 매개변수 기본값은 함수 정의 시 선언한 매개변수 개수를 나타내는 함수 객체의 length 프로퍼티와 arguments 객체에 아무런 영향을 주지 않음
function sum(x, y = 0){
  console.log(arguments);
}

console.log(sum.length);	// 1

sum(1);			// Arguments { '0': 1 }
sum(1, 2);		// Arguments { '0': 1, '1': 2 }
profile
Hello zoni-World ! (◍ᐡ₃ᐡ◍)

0개의 댓글