Article | [JS] 프로퍼티 어트리뷰트, 생성자 함수, 함수 객체

noopy·2021년 10월 8일
1

✏️ STUDY

목록 보기
5/10

팀원들과 함께하는 모던 JS 딥다이브 스터디 5 - 6차 💕

🍡 Property Attribute

Property Descriptor 객체

  • Property Attribute에 관한 정보를 제공하는 객체

Property Attribute란?

[[Value]],
[[Writable]], // default: true
[[Enumerable]], // default: true
[[Configurable]] // default: true

프로퍼티의 상태를 나타내는 내부 슬롯

  • 확인방법: Object.getOwnPropertyDescriptor()
  • 객체의 모든 Property Attribute 확인방법: Object.getOwnPropertyDescriptors()

데이터 프로퍼티 VS 접근자 프로퍼티

데이터 프로퍼티

  • 키: 값으로 구성된 일반적인 프로퍼티
  • 프로퍼티 생성 시 기본값으로 자동 정의됨
[[Value]],
[[Writable]], // 변경 여부
[[Enumerable]], // 열거 여부
[[Configurable]] // 재정의 여부 (삭제, 변경) ⭐️

👉🏻 [[Configurable]]이 false, [[Writable]]이 true 일 땐?
변경 가능. 삭제 불가

접근자 프로퍼티

  • 데이터 프로퍼티의 값을 get하거나 set할 때 사용하는 접근자 함수로 구성됨.
[[Get]],
[[Set]],
[[Enumerable]],
[[Configurable]]

접근자 프로퍼티로 프로퍼티 값 저장하기

바깥에서 접근자 프로퍼티의 값 설정은 함수 호출이 아닌
일반 프로퍼티를 설정하는 것과 같아 보인다!

const address = { }

address.fullName = 'Guro-gu Seoul' 
// 일반 프로퍼티에 할당하는 것처럼 보이지만, setter 함수가 호출된 것
console.log(address.fullName) // 'Guro-gu Seoul'

프로퍼티 정의

사용방법:
1. Object.defineProperty(객체, property, 옵션)
2. Object.defineProperties(객체, { property: {옵션} })
⚠️ 옵션 부분을 빈 객체로 둘 경우 undefined와 false로 초기화된다.

객체 변경 방지

객체는 변경 가능한 값으로 내부 프로퍼티를 재할당하지 않고 직접 변경할 수 있다는 장점이 있지만, 개발자가 실수로 프로퍼티를 변경해도 코드가 복잡해질 수록 추적하기가 쉽지 않다.
이를 위해 객체의 변경을 방지하는 다양한 메서드들이 존재한다.

👉🏻 얕은 변경 방지

Object.preventExtensions

  • 객체의 확장(추가)을 금지.
  • 확장이 가능한 객체인가? Object.isExtensible()

객체확장연습

Object.seal

  • 객체를 밀봉! 📦 = 꽁꽁싸서 더이상 추가나 삭제를 못하게 함
  • 밀봉된 객체인가? Object.isSealed

객체밀봉연습

Object.freeze

  • 객체를 freeze! 📦 = 걍 얼림. read만 가능
  • 동결된 객체인가? Object.isFrozen

객체동결연습

👉🏻 깊은 객체 변경 방지
재귀 돌려돌려 돌림판 ~ 🤸🤸🤸

깊은 객체 변경 방지

🍡 생성자 함수와 객체 생성

  • 생성자 함수: new 연산자와 호출해 객체(인스턴스)를 생성하는 함수
  • 인스턴스: 생성자 함수에 의해 생성된 객체

⚠️ 똑같은 함수지만
new 키워드로 호출하면 생성자 함수,
그냥 호출하면 일반함수!

둘을 구별하기 위해 생성자 함수의 첫 글자는 대문자로!

😉 알아보기

생성자 함수는 붕어빵 틀과 비슷하다!
붕어빵을 만들기 위해 붕어빵 틀을 만들어 복사하는 것처럼
생성자 함수(붕어빵 틀)로 인스턴스(붕어빵) 여러 개를 만들어 손쉽게 판매~!

반환문이 보이지 않는데?

JS 엔진이 (런타임 이전에)
암묵적으로 인스턴스({} (빈 객체))를 생성하고
생성자 함수 내부 this에 인스턴스가 바인딩되고
인스턴스 초기화 과정을 거친후
인스턴스가 바인딩된 this를 반환한다.

반환문 내부에서 다른 객체를 return

return 문의 명시된 객체가 반환

반환문 내부에서 원시값 return

원시값은 무시되고 인스턴스가 바인딩된 this를 반환

⭐️ 생성자 함수와 일반 함수의 차이점

  • 일반 함수로 호출 시: 함수 객체 내부 메서드 [[Call]]이 호출됨
    👉🏻 [[Call]]을 내부 메서드로 가진 함수 객체:
    callable (모든 함수에 해당)
  • 생성자 함수로 호출 시: 함수 객체 내부 메서드 [[Construct]]가 호출됨
    👉🏻 [[Construct]]를 내부 메서드로 가진 함수 객체:
    constructor
    반대: non-constructor

constructor VS non-constructor

  • constructor: 함수 | 생성자 함수로서 호출할 수 있는 함수 객체
    함수 선언문, 함수 표현식, 클래스
  • non-constructor: 생성자 함수로서 호출할 수 없는 함수 객체
    ex) 메서드, 화살표 함수


누가 봐도 형태가 이상해... 안배워도 non-constructor 인지 알 것 같은 이 기분...

⭐️⭐️ new.target

매우 유용하면서 중요한 것 같으니 별이 두 개 ⭐️_⭐️

함수 내부에서 new.target의 역할은
해당 함수의 생성자 함수 호출 여부를 파악해 로직을 추가해줄 수 있다는 점!!
프로젝트할 때 무작정 썼었는데 여기서 이해가 된다

  • 생성자 함수로서 호출됐는가? new.target === 함수 자신
  • 아닌가? new.target === undefined

생성자 함수로 만들어 주기

빌트인 생성자 함수와 주의사항

대부분의 빌트인 생성자 함수들은 위와 같이 new 연산자 호출 여부를 파악해
자동으로 new 붙여서 호출해준다.

String, Number, Boolean

String, Number, Boolean 빌트인 생성자 함수들은
new 키워드를 붙이지 않으면 데이터 타입을 변환시킨다.

👉🏻 어떻게 원시값이 메서드를 갖지?

이터러블, 이터레이터 간단 복습


new String()로 반환된 객체 내부에 [Iterator]가 있어서
이터러블 프로토콜을 따르는 for of문으로 돌려봤더니 순회가 잘됐다!


참고) https://velog.io/@jeongs/TIL-함수형-프로그래밍

new Number()로 반환된 객체는 객체 내부에 [Iterator]가 구현되어 있지 않아서 순회가 되지 않는 것 같다!

함수 객체

arguments 프로퍼티

모든 함수 객체는
함수 호출 시 전달된 인수의 정보를 담고 있는 유사 배열 객체인
arguments를 프로퍼티로 갖고 있다.

특징

  • 함수 내부에서 지역 변수로 사용됨.
  • 매개변수 개수와 인수의 개수가 차이나도 에러가 발생하지 않음.
    - 초과된 인수는 무시되지만, arguments 객체에 보관됨.

    👉🏻 arguments 객체는 유사배열객체이므로 배열 메서드를 사용할 수 없음. 이러한 불편함을 해결하기 위해 rest parameter가 탄생했다고 함...!

토론

느낀점

이번 회차부턴 스터디 인원이 줄어들지 않고 감사하게도 늘어나서,
모든 스터디원이 발표하지 않고 주마다 나눠서 발표하기로 했다!
그에 관한 후기는 나중에 여기에 남기기로 하고...

16, 17, 18장에 대해 읽어보니
생각보다 시간이 지나면 잊어버릴 휘발유성 내용들이 좀 많은 것 같아서
특히나 나같이 기억이 잘 증발하는 사람에겐 밑줄 친 부분들이라도 정리하는 것이 필요하다 생각했다...!

이전에도 정리했었던 덕분에 이터러블 관련 내용들도
오늘 발표 자료 준비하며 한번 더 상기시킬 수 있었던 만큼
이번 발표 자료들도 추후에 나에게 도움이 되기를 🙏

profile
💪🏻 아는 걸 설명할 줄 아는 개발자 되기

0개의 댓글