[Effective JavaScript] 함수, 메서드, 생성자 호출의 차이를 이해하자

김범식·2023년 6월 28일
0

Effective JavaScript

목록 보기
8/33
post-thumbnail

객체지향 프로그래밍에 익숙하다면 함수, 메서드, 클래스 생성자 이렇게 세 개의 요소로 생각하기 쉽다. 하지만 자바스크립트에서는 function을 사용하는 서로다른 패턴일 뿐이다.



📌 일급 객체
자바스크립트에서 함수는 일급 객체이다. 다른 객체와 마찬가지로 함수가 값으로 취급된다는 것을 의미한다. 즉 함수를 매개변수, 반환값, 변수에 할당등이 가능하다. 이는 함수형 프로그래밍이나 콜백 패턴과 같은 고급 프로그래밍 기법을 가능하게 한다.

function hello(username){
	return "hello "+ username;
}

hello("world") //hello world

다음 예제는 보이는 그대로 동작한다.



📌 JavaScript에서 this는 현재 실행 중인 코드의 컨텍스트를 가리키는 특수한 키워드입니다. this는 함수 내부에서 사용되며, 함수가 호출될 때 동적으로 결정됩니다. this의 값은 함수를 호출하는 방식과 실행 컨텍스트에 따라 달라집니다.

this의 값은 다음과 같은 경우에 결정될 수 있다.

  1. 함수 호출 시: 함수를 어떻게 호출하느냐에 따라 this가 결정된다.
  2. 메서드 호출 시: 객체의 메서드로서 함수가 호출되는 경우, this는 해당 객체를 가리킨다.
  3. 생성자 함수 호출 시: 생성자 함수로 객체 인스턴스를 생성할 때, this는 새로 생성된 객체를 가리킨다.



var obj = {
	hello:function(){
		return "hello, " + this.username;
		},
	usename : "jhon"
}

obj.hello(). //''hellow, jhon"

자바스크립트에서 매서드는 함수로 동작하는 객체의 프로퍼티이다. 여기서 hello()obj에 선언 되었기 때문에 thisobj에 바인딩 되었다고 생각할 것이다. 그렇다면 다음 코드를 살펴보자

var obj2 = {
	hello: obj.hello,
	username : "aron"
}

obj2.hello(); // hello, aron
	

아까와는 전혀 다른 결과가 출력된다.

obj.hello() 표현식은 obj에서 hello프로퍼티를 찾고, 수신자 객체 obj로 호출한다.

obj2.hello() 표현식은 obj2hello프로퍼티를 찾고 이는 obj.hello()와 동일한 함수지만 수신자 객체는 obj2가 된다.



이처럼 어떤 객체의 메서드를 호출하면 메서드를 찾고, 해당 객체를 수신자 객체로 사용한다.

function hello(){
	return "hello,  "+ this.username;
}



이 방법은 여러 개의 객체에서 공유하는 함수를 미리 선언해 둘 때 유용하게 사용한다.

var obj1 = {
	hello:hello,
	username : "abc"
}

obj1.hello() // hello abc

var obj2 = {
	hello:hello,
	username:"def"
}

obj2.hello() // hello def



하지만 this를 사용하는 함수는, 메서드로써 호출할 때는 유용하지만 함수로써 호출하면 특별히 유용하지는 않다.

hello() // hello undefined

메서드가 아닌 함수를 호출하면 전역객체가 그 수신자가 되고 , 이경우에는 username이라는 프로퍼티가 없어서 undefined값을 만들어 내므로 오히려 해가 된다.



전역객체로 바인딩 하는것은 기본적으로 문제의 소지가 있기 때문에 ES5의 스트릭트 모드에서는 this의 기본 바인딩을 undefined로 변경되었다.

function hello(){
	"use strict"
	return "hello,  "+ this.username;
}

hello();  //에러 발생



매서드와 일반 함수처럼 생성자 또한 function으로 정의한다.

function User(name, passwordHash){
	this.name = name;
	this.passwordHash = passwordHash;
}



다음과 같이 new 연산자로 User를 실행하면 생성자 처럼 처리된다.

var u = new User("abcd", " 123123123 );

u.name; // "abcd"



메서드나 함수와는 다르게 , 생성자 호출은 this의 값으로 새로운 객체를 전달하고, 암묵적으로 이 객체를 결과로 반환한다. 즉 생성자 함수의 주요한 역할은 객체를 초기화 시키는 것이다.



기억할 점

  • 메서드 호출은 메서드 프로퍼티를 찾을 객체, 즉 해당 호출을 받는 수신자 객체를 제공한다.
  • 함수 호출은 전역 객체(스트릭트 모드 함수에서는 undefined)를 수신자 객체로 규정한다. 메서드를 함수처럼 호출하는 문법은 별로 유용하지 않다.
  • 생성자는 new로 호출하고, 새로운 객체를 수신자로 받는다.
profile
frontend developer

0개의 댓글