다시 처음부터 JavaScript || 함수의구분

문규찬·2021년 12월 2일
0
post-thumbnail

✅ 출처 : 다시 처음부터 자바스크립트 게시글은 이웅모(님) '모던 자바스크립트 Deep Dive' 를 기록합니다

ES6 이전의 함수는 사용 목적에 따라 명확히 구분되지 않습니다. ES6 이전의 모든 함수는 일반함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있습니다.
(callable 이면서 constructor)

var foo = function() {
	return 1;
    }

//일반함수 호출
foo()    ---> 1

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

//메서드로서 호출
const obj={
foo:foo
}
obj.foo() ----> 1

메서드

ES6 이전 사양에는 메서드에 대한 명확한 정의가 없었습니다.
일반적으로 메서드는 객체에 바인딩된 함수를 일컫는 의미로 사용되었습니다.

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

const obj={
	x:1,
    	foo(){return this.x},
        bar : function () { return this.x}   --> 메서드가 아닌 일반함수
      }

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

ES6 사양에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor입니다. 따라서
ES6 메서드는 생성자 함수로서 호출할 수 없습니다.

new obj.foo() // TypeError
new obj.bar() // bar {}

obj.foo는 constructor가 아닌 ES6 메서드 이므로 prototype 프로퍼티가 없습니다.

ES6 메서드는 자신을 바인딩한 객체를 가리키는 🔴내부 슬롯 [[HomeObject]]를 갖습니다.
(내부슬롯 정리는 따로 포스팅 할 예정)

super 참조는 내부 슬롯 [[HomeObject]]를 사용하여 수퍼클래스의 메서드를 참조하므로 내부 슬롯 [[HomeObject]]를 갖는 ES6 메서드는 super 키워드를 사용할 수 있습니다!
(이 부분은 이해하기 힘들지만 천천히 넘어가 봅시당~~)

⭐️ 화살표 함수 ⭐️

화살표 함수는 function 키워드를 대신하여 기존의 함수 정의 방식보다 간략하게 함수를 정의할 수 있습니다. ( 생김새는 생략!!)

화살표 함수와 일반 함수의 차이 ⭐️⭐️

1. 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor 입니다!!

const Foo = () => {};
new Foo() // TypeError

Foo.hasOwnProperty('prototype') // false

화살표 함수는 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없습니다!

2. 중복된 매개변수 이름 선언 불가!

const arrow=(a,a)=> a+a;
//SyntaxError

3. 화살표함수는 함수 자체의 this,arguments, super, new.target 바인딩을 갖지 않습니다. ⭐️
화살표 함수 내부에서 this,arguments, super, new.target을 참조하면 스코프 체인을 통해 상위 스코프의 것을 참조합니다.

this ⭐️

화살표 함수가 일반 함수와 구별되는 가장 큰 특징은 바로 this 입니다

화살표 함수의 this는 일반 함수와 다르게 동작합니다.
이는 '콜백 함수 내부의 this 문제' 로 콜백함수의 this가 외부 함수의 this와 다르기 때문에 이 문제를 해결하기 위해 의도적으로 설계된 것입니다.

this 바이딩은 함수의 호출 방식, 즉 함수가 어떻게 호출되었는지에 따라 동적으로 결정됩니다.
다음 예제를 살표봅시다.

add 메서드에서 this는 메서드를 호출한 객체(prefixer)를 카리킵니다.
그런데 map의 인수로 전달한 콜백 함수의 내부인 this는 undefined를 카리키죠
이는 map 메서드가 콜백 함수를 일반 함수로서 호출하기 때문입니다.

this는 일반 함수로서 호출되는 모든 함수 내부의 this는 전역 객체를 가라킵니다.
그런데 클래스 내부의 모든 코드에는 strict mode가 암묵적으로 적용되는데 strict mode에서 일반 함수로서 호출된 모든 함수 내부의 this는 전역 객체가 아니라 undefined가 바인딩되므로 일반 함수로서 호출되는 map 메서드의 콜백 함수 내부 this 또한 undefined가 바인딩됩니다.

이때 발생하는 문제가 바로 '콜백 함수 내부의 this 문제' 입니다. 콜백 함수의 this가 서로 다른 값을 가리키고 있기 때문에 TypeError가 발생!

이를 해결하기 위해 ES6이전에는 다음과 같은 방법을 사용했습니다.

  1. add메서드를 호출한 prefixer 객체를 가리키는 this를 일단 회피시킨 후에 콜백 함수 내부에서 사용
add(arr){
	const that = this; // this를 일단 회피시킵니다.
    	return arr.map(function(item) { return that.prefix + '' +item})
        }
  1. map함수의 두번째 인수로 add 메서드를 호출한 prefixer 객체를 가리키는 this를 전달!
add(arr){
    	return arr.map(function(item) { return this.prefix + '' +item},this)
        }
  1. Function.prototype.bind 메서드를 사용하여 add메서드를 호출한 prefixer 객체를 가리키는 this를 바인딩 합니다.
add(arr){
	return arr.map(function(item){
    	return this.prefix + ' ' + item;
        }.bind(this))
        }
  1. 화살표 함수!

화살표 함수는 함수 자체의 this 바인딩을 갖기 않습니다. 따라서 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조합니다!! 이를 lexical this라 합니다.

0개의 댓글