-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
17장:생성자 함수에 의한 객체 생성 #9
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다 👍
Object 생성자 함수 외에도 String, Number, Boolean, Function, Array, Date, RegExp. | ||
promise 등의 빌트인 생성자 함수를 제공한다.<br/><br/> | ||
|
||
> 직관적이고 간편한 객체 리터럴 생성 방식이 있는데 왜 생성자 함수로 객체를 생성해야 할까? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 종종 들었던 의문인데 여기서 이해가 되네요.
객체 리터럴로 생성하면 그 즉시 인스턴스화 되어 메모리에 올라가는데, 생성자 함수를 통해 객체를 생성하면 new로 호출할 때만 메모리에 올라간다는 점도 차이가 아닐까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 뭔가 정확한 이유에 대해서는 생각해본 적 없는 거 같아요.. 그치만 책에서도 객체 리터럴을 더 사용하는 것이 더 간편하다고.. 생성자 함수는 그다지 유용해보이지 않는다구 하네요
```jsx | ||
// 일반 함수로서 호출 | ||
const Circle3 = Circle(15); | ||
|
||
console.log(circle3); //undefined | ||
``` | ||
|
||
→ 반환문이 없으므로 암묵적으로 undefined 반환 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
일반 함수와 생성자 함수를 구분하기 힘들 것 같아요
그래서 좀 더 명시적인 class 문법이 생긴 걸까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class 문법을 쓰는 이유에 대해 이 글 에서 잘 설명해둔 것 같습니다
간단히 생성자함수와 클래스의 차이를 요약하자면
- new 연산자 없이 호출 : 생성자 함수는 일반 함수로 호출되지만, 클래스는 오류가 난다.
- extends 와 super : 생성자 함수에는 제공되지 않지만, 클래스에는 제공된다.
- 호이스팅 : 생성자 함수에는 호이스팅이 발생하나, 클래스에는 발생하지 않는다.
- strict mode : 생성자 함수에는 암묵적으로 지정되지 않지만, 클래스에는 암묵적으로 지정된다.
[[Enumerable]]
: 클래스의constuctor
, 프로토타입 메서드, 정적 메서드는 모두[[Enumerable]]
의 값이false
다.
이렇게 되겠네요
[[Call]] 을 갖는 함수 객체: callable | ||
|
||
[[Construct]]를 갖는 함수 객체: constructor | ||
|
||
[[Construct]]을 갖지않는 함수 객체: non-constructor | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 JS에서 함수형 프로그래밍을 따르며 함수 그 자체로 생성자 역할을 하기 위해 내부적으로 메서드를 추가로 가지고 있었네요
과연 이런 방법이 개발할 때 더 편한지, 유지보수에 유리할지 이야기해보면 좋을 거 같아요
console.log(bool, typeof bool); // true boolean | ||
``` | ||
|
||
→ IE에서는 new.target을 지원하지 않는다. 사용할 수 없는 상황이라면 스코프 세이프 생성자 패턴을 대신 사용할 수 있다고 합니다. IE 환경을 구현하실 분은.. 참고 하시길..^^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
24년 기준으로 IE가 군대에서도 deprecated됐습니다... 이제 edge에서 IE mode를 사용해요... 저도 알고싶지 않았습니다
console.log(obj); // {} | ||
``` | ||
|
||
String, Number, Boolean 생성자 함수는 new 연산자 없이 호출하면 문자열, 숫자, 불리언 값을 반환한다. 이를 이용해 데이터의 타입을 변환하기도 한다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Number("문자열") 로 사용하면 Number로 변환해주죠.
그러면 Number.isNaN() 과 같은 메서드는 어떻게 구현된 걸까요..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isNaN
와 Number.isNaN
의 내부 로직 차이가 있네요
//엄격하지 않은(약간 멍청한) NaN 판별 메소드
//문자열 `"NaN"`도 NaN으로 판단하다
isNaN = function(value) {
return Number(value) !== Number(value);
};
//더 엄격하고, 진짜 NaN만
Number.isNaN = function(value) {
return typeof value === "number" && value !== value;
};
//비교
isNaN("NaN"); // true (문자열 -> NaN)
isNaN(undefined); // true (undefined -> NaN)
Number.isNaN("NaN"); // false (문자열)
Number.isNaN(undefined); // false
Number.isNaN(NaN) //true (진짜 NaN)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://tc39.es/ecma262/#sec-isnan-number
ES isNaN 스펙입니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ecma 스펙 읽는게 어려워요
가이드나 읽는 꿀팁이 있나요?
@hanu9257
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
무지 빠르시네요 🚀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨어용~
|
||
차이점은 **일반 객체는 호출할 수 없지만 함수는 호출할 수 있다.** | ||
|
||
따라서 함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드는 물론, 함수로서 동작하기 위해 함수 객체만 을 위한 [[Environment]], [[FormalParameters]] 등의 내부 슬롯과 [[call]], [[Construct]] 같은 내부 메서드를 **추가로** 가지고 있다 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
한글로 "함수 객체"라고 써져 있어서 무슨 얘긴가 했는데 Execution record의 Function Object에 대한 내용이었네요. 관련된 영상 남겨둡니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hanu : 함수 객체는 언제 초기화되나요??
hanu : 호이스팅 됨과 동시에 함수가 초기화된다. 그런데 언제 내부 슬롯 [[call]], [[construct]]가 초기화되는가?
[[construct]]와 [[non-construct]]를 동시에 가지지 않는데 어떻게 구분해서 초기화하는지??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gooood
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#10 에 대해 ECMAScript 문서를 읽고서야 이해한 것 같아서 공유해요.
배경지식
우선 constructor라는 말은 ECMAScript의 용어 정의에 존재해요.
그리고 Arrow function, Function의 initiating을 하는 부분의 spec은 각각 다음과 같아요.
Arrow function
Function
차이점
일반 Function은 initiating을 할 때 5. Perform MakeConstructor(F)
가 존재하는 반면 Arrow function은 initiating을 할 때 해당 함수를 호출하지 않아요.
그리고 바로 이 MakeConstructor
내부에서 function object의 internal method인 F.[[construct]]
가 초기화 되게 되네요.
결론
ECMAScript spec에서부터 각 함수를 처리하는 방법이 다르고 이에 따라 function object의 internal method가 초기회돼요.
참고
찾아보다 알게 된 부분인데 모든 함수는 [[call]]
internal method를 가지게 돼요. 따라서 이런 object를 constructor, constructor function, constructor function object등 다양한 이름으로 부를 수 있어요.
읽어보시고 이해가 안 되거나 궁금한 점이 생기시면 댓글 달아 주세요 😎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
화살표 함수와 일반 함수의 실행 컨텍스트 차이에 대해서도 살펴볼 수 있네요~ 좋아용 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정리하느라 고생하셨어요~~~~생성자 함수에 대해 깊이 이해할 수 있는 시간이었습니다! 💯
일반 함수로서 호출 → 내부 메서드 [[Call]] 이 호출됨 | ||
|
||
생성자함수로 호출 → 내부 메서드 [[Construct]] 이 호출됨 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❗ 이를 통해 함수로써 기능할건지, 생성자로써 기능할건지가 결정되는 거군요! 새로운 지식 하나 알아갑니다 👍
|
||
일반함수와 생성자 함수는 특별한 형식적 차이는 없다. | ||
|
||
그래서 생성자 함수는 일반적으로 **첫 문자를 대문자로** 기수하는 파스칼케이스로 이름을 지어 일반 함수와 구별할 수 있도록 한다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
컨벤션의 중요성인 것 같습니다. 컨벤션이 모든걸 막아주지는 않지만 그래도 어느정도는 효과가 있다고 생각해요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 여기서 이런 컨벤션이 있는건 몰랐네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수 컴포넌트의 모태가 클래스 컴포넌트이고 클래스의 모태가 생성자 함수이니 함수 컴포넌트가 파스칼 케이스를 쓰는것도 여기서부터 유래된 거겠네요
```jsx | ||
// 생성자 함수 | ||
function Circle(radius) { | ||
// 이 함수가 new 연산자와 함께 호출되지 않았다면 new.target은 undefined다. | ||
if (!new.target) { | ||
// new 연산자와 함께 생성자 함수를 재귀 호출하여 생성된 인스턴스를 반환한다. | ||
return new Circle(radius); | ||
} | ||
this.radius = radius; | ||
} | ||
|
||
const circle = Circle(5); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brilliant!!!!!!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
내부적으로 재귀호출해서 new를 붙여서 다시 호출한다는 이야기군요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
빠른 정리 감사합니다!! 최고 최고~
|
||
일반함수와 생성자 함수는 특별한 형식적 차이는 없다. | ||
|
||
그래서 생성자 함수는 일반적으로 **첫 문자를 대문자로** 기수하는 파스칼케이스로 이름을 지어 일반 함수와 구별할 수 있도록 한다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 여기서 이런 컨벤션이 있는건 몰랐네요
console.log(obj); // {} | ||
``` | ||
|
||
String, Number, Boolean 생성자 함수는 new 연산자 없이 호출하면 문자열, 숫자, 불리언 값을 반환한다. 이를 이용해 데이터의 타입을 변환하기도 한다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isNaN
와 Number.isNaN
의 내부 로직 차이가 있네요
//엄격하지 않은(약간 멍청한) NaN 판별 메소드
//문자열 `"NaN"`도 NaN으로 판단하다
isNaN = function(value) {
return Number(value) !== Number(value);
};
//더 엄격하고, 진짜 NaN만
Number.isNaN = function(value) {
return typeof value === "number" && value !== value;
};
//비교
isNaN("NaN"); // true (문자열 -> NaN)
isNaN(undefined); // true (undefined -> NaN)
Number.isNaN("NaN"); // false (문자열)
Number.isNaN(undefined); // false
Number.isNaN(NaN) //true (진짜 NaN)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정리하느라 수고 많으셨숩니다~~🍥
Object 생성자 함수 외에도 String, Number, Boolean, Function, Array, Date, RegExp. | ||
promise 등의 빌트인 생성자 함수를 제공한다.<br/><br/> | ||
|
||
> 직관적이고 간편한 객체 리터럴 생성 방식이 있는데 왜 생성자 함수로 객체를 생성해야 할까? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 뭔가 정확한 이유에 대해서는 생각해본 적 없는 거 같아요.. 그치만 책에서도 객체 리터럴을 더 사용하는 것이 더 간편하다고.. 생성자 함수는 그다지 유용해보이지 않는다구 하네요
## 자바스크립트 엔진은 어떻게 constructor와 non-constructor를 구분할까? | ||
|
||
(생성자로 동작하는 함수와 생성자로 동작하지 않는 함수를 구분한다는 뜻) | ||
|
||
**constructor**: 함수선언문, 함수 표현식, 클래스(클래스도 함수다) | ||
|
||
**non-constructor**: 메서드(ES6 메서드 축약 표현), 화살표 함수 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
만약에 non-constructor인 함수를 new 생성자로 생성하려고 하면 TypeError가 발생하네요.(책에서도 있는 내용)
const arrow = () => {};
new arrow(); //Uncaught TypeError: arrow is not a constructor
```jsx | ||
const circle1 = { | ||
radius: 5, | ||
getDiameter() { | ||
return 2 * this.radius; | ||
}, | ||
}; | ||
|
||
const circle2 = { | ||
radius: 10, | ||
getDiameter() { | ||
return 2 * this.radius; | ||
}, | ||
}; | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@whddltjdwhd 의 질문
Q: getDiameter
을 전역으로 선언하면 바인딩이 안 되나요?
@hanu9257 의 답변
A: 함수 바인딩을 사용하면 됩니다
```jsx | ||
// 생성자 함수 | ||
function Circle(radius) { | ||
// 이 함수가 new 연산자와 함께 호출되지 않았다면 new.target은 undefined다. | ||
if (!new.target) { | ||
// new 연산자와 함께 생성자 함수를 재귀 호출하여 생성된 인스턴스를 반환한다. | ||
return new Circle(radius); | ||
} | ||
this.radius = radius; | ||
} | ||
|
||
const circle = Circle(5); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
내부적으로 재귀호출해서 new를 붙여서 다시 호출한다는 이야기군요
-스터디 정리 담당자 추가
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다! 스터디 참여하지 못해서 아쉽네요
자바스크립트의 독특한 함수의 특징을 살펴볼 수 있어서 재밌는 단원이었습니다 🐧
|
||
차이점은 **일반 객체는 호출할 수 없지만 함수는 호출할 수 있다.** | ||
|
||
따라서 함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드는 물론, 함수로서 동작하기 위해 함수 객체만 을 위한 [[Environment]], [[FormalParameters]] 등의 내부 슬롯과 [[call]], [[Construct]] 같은 내부 메서드를 **추가로** 가지고 있다 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
화살표 함수와 일반 함수의 실행 컨텍스트 차이에 대해서도 살펴볼 수 있네요~ 좋아용 👍
|
||
일반함수와 생성자 함수는 특별한 형식적 차이는 없다. | ||
|
||
그래서 생성자 함수는 일반적으로 **첫 문자를 대문자로** 기수하는 파스칼케이스로 이름을 지어 일반 함수와 구별할 수 있도록 한다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수 컴포넌트의 모태가 클래스 컴포넌트이고 클래스의 모태가 생성자 함수이니 함수 컴포넌트가 파스칼 케이스를 쓰는것도 여기서부터 유래된 거겠네요
생성자 함수로 객체를 생성하는 법에 대해 알아봅쉬다 ~ ☃️