함수 심화학습
1. 함수 바인딩
func.bind(context, ...args) 는 this 가 context 로 고정되고 인수도 고정된 함수 func 을 반환한다.
bind 는 보통 객체 메서드의 this 를 고정해 어딘가에 넘겨줄 때 사용한다.
기존 함수의 인수 몇 개를 고정한 함수를 부분 적용 함수 또는 부분 함수라고 부른다.
부분 적용은 같은 인수를 여러 번 반복하고 싶지 않을 때 유용하다. send(from, to)라는 함수가 있는데 from 가 있는데 from 을 고정하고 싶다면 send(from, to)의 부분함수를 구현해 사용하면 된다.
-> 부분 적용 : 만약 this 뿐만 아니라 인자까지 고정하고 싶다면, let bound = func.bind(context, [arg1], [arg2], ...) 을 사용한다. 이때 추가 인수는 그대로 전달된다.
2. 화살표 함수
this 가 없기 때문에 new 와 함께 호출할 수 없다.
arguments 를 지원하지 않는다. (argument 란 모든 인수에 접근할 수 있게 해주는 유사 배열 객체이다.)
super 가 없다.
객체 프로퍼티 설정
1. 프로퍼티 플래그와 설명자
지금까지 객체의 프로퍼티를 '키-값' 쌍의 관점에서만 다뤘다면 이제는 좀 더 유연하게 만들어주는 추가 구성 옵션 몇 가지를 더 알아보자.
- 프로퍼티 플래그
객체 프로퍼티는 값과 함께 플래그(Flag)라 불리는 특별한 속성 3가지를 가진다.
1) writable: ture 이면 값 수정 가능
2) enumerable: true 이면 반복문 사용해 나열 가능
3) configurable: true 이면 프로퍼티 삭제나 플래그 수정 가능
평범한 방식으로 프로퍼티를 만든다면, 위 속성은 모두 true 이다.
- 관련 함수들
1) Object.getOwnPropertyDescriptor(obj, propertyName) 메서드 사용 시 특정 프로퍼티에 대한 정보를 모두 얻을 수 있다. 프로퍼티 설명자라 불리는 객체를 반환한다.(세 플래그와 프로퍼티 값이 들어있다.)
2) Object.defineProperty(obj, propertyName, descriptor) (descriptor 는 적용하고자 하는 프로퍼티 설명자) 객체에 해당 프로퍼티가 있으면 플래그를 원하는 대로 변경한다. 프로퍼티가 없으면 새로운 프로퍼티를 만드는데 이때 플래그 정보가 없으면 플래그 값은 자동으로 false 가 된다.
- configurable 플래그가 false 이면서 writable 플래그가 false 이면 영원히 변경 불가한 프로퍼티를 만들 수 있다.
2. 프로퍼티 getter 와 setter
객체의 프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티가 있다. 전자는 지금까지 사용한 모든 프로퍼티이고 후자는, 본질은 함수인데, 이 함수는 값을 획득하고 설정하는 역할을 한다. 그런데 외부 코드에서 봤을 때는 함수가 아닌 일반적인 프로퍼티처럼 보인다.
1) getter 와 setter
접근자 프로퍼티는 getter 와 setter 메서드로 표현된다. 객체 리터럴 안에서 getter 와 setter 은 get 과 set 으로 표현된다.
getter 에서는 obj.propName 을 사용해 프로퍼티를 읽으려 할 때 실행되고 setter 메서드는 obj.propName = vale 로 프로퍼티에 값을 할당하려 할 때 실행된다.
접근자 프로퍼티를 사용하면 함수처럼 호출하지 않고 일반 프로퍼티에서 값에 접근하는 것처럼 평범하게 프로퍼티 값을 얻을 수 있다.
getter 와 setter 메서드를 구현하면 객체엔 가상의 프로퍼티가 생기게 된다. 이는 읽고 쓸 수 있으나 실제로 존재하진 않는다.
2) 접근자 프로퍼티 설명자
접근자 프로퍼티와 데이터 프로퍼티는 설명자가 다르다.
접근자 프로퍼티엔 설명자 value, writable 이 없는 대신에 get 과 set 함수가 있다.
getter 와 setter 를 실제 프로퍼티 값을 감싸는 래퍼로 활용하면 프러퍼티 값을 원하는 대로 통제할 수 있게 된다.
접근자 프로퍼티를 이용하면 호환성을 높일 수 있다.(생성자 함수를 직접 수정하면 기존의 코드를 모두 수정해야 한다. 그러나 접근자 프로퍼티를 사용하면 기존의 것은 그대로 두고 새로운 것을 추가하기만 하면 된다.)
프로토타입과 프로토타입 상속
- 프로토타입 상속
기존에 있던 객체에 약간의 기능만을 얹은 객체를 생성하고 싶다면 프로토타입 상속을 이용하자.
자바스크립트의 모든 객체엔 숨김 프로퍼티[[Prototype]]이 있는데, 이 프로퍼티는 객체나 null 을 가리킨다.
[[Prototype]]이 참조하는 객체를 프로토타입이라고 한다.
obj.proto 를 사용하면 프로토타입에 접근할 수 있다. 이는 [[prototype]]의 getter setter 로 쓰이는데 요즘은 잘 사용하지 않는다.
객체에서 프로퍼티를 읽거나 메서드를 호출하려는데 해당하는 프로퍼티나 메서드가 없으면 js 는 프로토타입에서 프러퍼티/메서드를 찾는다.
접근자 프러퍼티가 아닌 데이터 프러퍼티를 다루고 있다면, 쓰기나 지우기와 관련된 연산은 프로토타입을 통하지 않고 객체에 직젖ㅂ 적용된다.(프로토타입은 읽기 전용이기 때문이다.) (접근자 프로퍼티는 상속자의 geter 와 setter 를 이용하므로 상속자의 getter 와 setter 을 이용해 값을 쓸 수 있다.)
메서드를 객체에서 호출했든 프로토타입에서 호출했든 this 는 언제나 . 앞의 객체이다.
for in 반복문은 객체 자체에서 정의한 프로퍼티와 상속 프로퍼티 모두를 순회한다. 반면 키값과 관련된 내장 메서드 대부분은 상속 프러퍼티는 제외하고 객체 자체 프로퍼티만을 대상으로 등록한다. has Own property 를 사용하면 상속 프러퍼티를 순회 대상에서 제외할 수 있다.
- 함수의 prototype 프로퍼티
생성자 함수를 사용해 객체를 만든 경우 프로토타입은 어떻게 동작할까?
생성자 함수로 객체를 만들면 생성자 함수의 프로토타입 정보를 이용해 [[prototype]]을 설정한다.
1) 생성자 함수에 기본으로 세팅되는 F.prototype 프로퍼티는 [[]] 와 다르다. 이는 new F 를 호출할 때 만들어지는 새로운 객체의 [[]] 를 설정한다 .
- f.prototype 의 값은 객체나 null 만 가능하다.
- 내장 객체의 프로토타입
모든 내장 객체는 다음의 규칙을 따른다.
- 메서드는 프로토타입에 저장된다.
- 객체 자체는 데이터만 저장한다. (객체가 프로토타입으로, 메서드가 구현된 거대한 객체를 참조한다.)
-원시값 또한 ㅍ래퍼 객체의 프로토타입에 nUmber.prototype 과 같은 메서드를 저장한다. 단 undefined null 은 예외이다.
내장 프로토타입은 수정이 가능하나 지양해야 한다.