forked from qwer0114/Javascript-Deep-Dive-Study
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# 16 - 프로퍼티 어트리뷰트 | ||
|
||
**내부 슬롯 (Internal Slot)** | ||
|
||
> 내자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 사용하는 의사 프로퍼티 (Pseudo Property) | ||
> | ||
**내부 메서드 (Internal Method)** | ||
|
||
> 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 사용하는 의사 메서드 (Pseudo Method) | ||
> | ||
내부슬롯을 프로퍼티를 통해 간접적으로 접근할 수 있다 !! | ||
|
||
## **16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체** | ||
|
||
**프로퍼티 어트리뷰트 (Property Attribute)** | ||
|
||
- 프로퍼티의 상태를 나타내는 어트리뷰트. | ||
- 자바스크립트 엔진이 프로퍼티를 생성할 때 기본값으로 자동 정의한다. | ||
|
||
### 프로퍼티 상태와 어트리뷰트 (Property Attribute) | ||
|
||
- 프로퍼티의 값 **(Value) ⇒ `[[Value]]`** | ||
- 값의 갱신 가능 여부 **(Writable) ⇒ `[[Writable]]`** | ||
- 값의 열거 가능 여부 **(Enumerable) ⇒ `[[Enumerable]]`** | ||
- 값의 재정의 가능 여부 **(Configurable) ⇒ `[[Configurable]]`** | ||
|
||
> 프로퍼티 어트리뷰트는 직접 접근할 수 없지만, `Object.getOwnPropertyDescriptor` 메서드를 통해 간접적으로 호출할 수 있다. | ||
> | ||
## 16.3 데이터 프로퍼티와 접근자 프로퍼티 | ||
|
||
### **데이터 프로퍼티** | ||
|
||
: Key, Value로 구성된 일반적인 프로퍼티 | ||
|
||
### **접근자 프로퍼티 (Accessor Property)** | ||
|
||
: 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 **접근자 함수 (Accessor Function)**로 구성된 프로퍼티. | ||
|
||
**접근자 프로퍼티의 동작 순서** | ||
|
||
1. 전달 받는 프로퍼티 키의 유효성을 검사한다. 프로퍼티의 키는 String 또는 Symbol 이어야 한다. | ||
2. 프로토타입 체인 (Prototype Chain)을 통해 프로퍼티를 검색한다. | ||
3. 검색된 프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인한다. | ||
|
||
## 16.4 프로퍼티 정의 | ||
|
||
새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 새로 정의하거나 재정의 하는 행위 | ||
|
||
- 프로퍼티의 값을 갱신 가능 여부 | ||
- 프로퍼티의 열거 가능 여부 | ||
- 프로퍼티의 재정의 가능 여부 | ||
|
||
등등을 새로 정의하거나 재정의 할 수 있다. | ||
|
||
## Object.defineProperty | ||
|
||
```jsx | ||
Object.defineProperty(객체의 참조, 데이터 프로퍼티의 키, 프로퍼티 디스크립터 객체) | ||
``` | ||
|
||
defineProperty를 사용했을 때 디스크립터 객체의 프로퍼티를 누락시키면 `undefined`, `false`가 기본값이 된다. | ||
|
||
## Object.defineProperties | ||
|
||
`Object.defineProperties`를 통해 여러개의 프로퍼티를 한 번에 정의할 수 있다. | ||
|
||
```jsx | ||
const person = { | ||
firstName: 'sedol' | ||
}; | ||
|
||
// 점 표기법 (Dot Notation) | ||
person.age = 20; | ||
|
||
// Object.definedProperty without Descriptor Object | ||
Object.defineProperty(person, 'lastName', { | ||
value: 'Lee' | ||
}); | ||
|
||
descriptor = Object.getOwnPropertyDescriptor(person, 'lastName'); | ||
|
||
console.log(Object.getOwnPropertyDescriptors(person)); | ||
``` | ||
|
||
```jsx | ||
{ | ||
age: {value: 20, writable: true, enumerable: true, configurable: true} | ||
firstName: {value: 'sedol', writable: true, enumerable: true, configurable: true} | ||
lastName: {value: 'Lee', writable: false, enumerable: false, configurable: false} | ||
} | ||
``` | ||
|
||
# 16.5 객체 변경 방지 | ||
|
||
기본적으로 객체는 변경 가능한 값이므로 재할당 없이 직접 변경할 수 있다. | ||
|
||
- 프로퍼티 추가, 삭제, 갱신 등 | ||
- Object.defineProperty, Object.defineProperties 등 | ||
|
||
**Object.preventExtensions** | ||
|
||
`Object.isExtensible()`를 통해 확장 금지 여부를 알 수 있다. | ||
|
||
**Object.seal** | ||
|
||
프로퍼티의 읽기와 갱신만 가능하다. | ||
|
||
- 프로퍼티 추가, 삭제, 재정의가 금지된다. | ||
|
||
`Object.isSealed()`를 통해 밀봉 여부를 알 수 있다. | ||
|
||
**Object.freeze** | ||
|
||
프로퍼티의 읽기만 가능하다. | ||
|
||
- 프로퍼티 추가, 삭제, 재정의, 갱신이 금지된다. | ||
|
||
`Object.isFrozen()`를 통해 동결 여부를 알 수 있다. | ||
|
||
## 불변 객체 | ||
|
||
앞서 살펴본 메서드는 **얕은 변경 방지 (Shallow Only) 방식**이다. | ||
|
||
상위의 프로퍼티만 변경이 방지되고, 그 안에 있는 **자식 객체는 영향을 받지 못한다.** | ||
|
||
→ 재귀적으로 Object.freeze를 수행한다 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# 17 - 생성자 함수에 의한 객체 생성 | ||
|
||
## 17.1 Object 생성자 함수 | ||
|
||
- **생성자 함수(constructor)** | ||
- `new` 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수 | ||
- 빈 객체 생성하여 반환 ⇒ 프로퍼티/메서드 추가 | ||
|
||
## 17.2 생성자 함수 | ||
|
||
### 생성자 함수 → 객체 생성 방식 | ||
|
||
- `this` : 자신의 프로퍼티/메서드를 참조하기 위한 **자기 참조 변수** | ||
|
||
인스턴스 생성 과정 | ||
|
||
1. 암묵적으로 인스턴스가 생성되고 `this`에 바인딩된다. | ||
2. `this`에 바인딩되어 있는 인스턴스를 초기화한다. (by 개발자) | ||
3. 암묵적으로 `this`를 반환한다 | ||
|
||
내부 메서드 [[Call]] 과[[Construct]] | ||
|
||
함수 객체는 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드는 물론, 함수로서 동작하기 위한 함수 객체만을 위한 [[Enviornment]], [[FormalParameter]] 등의 내부 슬롯과 [[Call]], [[Construct]] 같은 내부 메서드를 추가로 가지고 있다. | ||
|
||
![Untitled](17%20-%20%E1%84%89%E1%85%A2%E1%86%BC%E1%84%89%E1%85%A5%E1%86%BC%E1%84%8C%E1%85%A1%20%E1%84%92%E1%85%A1%E1%86%B7%E1%84%89%E1%85%AE%E1%84%8B%E1%85%A6%20%E1%84%8B%E1%85%B4%E1%84%92%E1%85%A1%E1%86%AB%20%E1%84%80%E1%85%A2%E1%86%A8%E1%84%8E%E1%85%A6%20%E1%84%89%E1%85%A2%E1%86%BC%E1%84%89%E1%85%A5%E1%86%BC%20c9567953f6044db7ac3b5d95e50a67bf/Untitled.png) | ||
|
||
### constructor와 non-constructor의 구분 | ||
|
||
자바스크립트 엔진은 함수 정의를 평가하여 함수 객체를 생성할 때 함수 정의 방식에 따라 함수를 constructor와 non-constructor로 구분한다. | ||
|
||
> constructor : 함수 선언문, 함수 표현식, 클래스 | ||
> | ||
> | ||
> **non - constructor** : 메서드, 화살표 함수 | ||
> | ||
### new 연산자 | ||
|
||
new 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작한다. | ||
|
||
함수 객체의 내부 메서드 [[Call]]이 호출되는 것이 아니라 [[Contruct]]가 호출된다. 단, new 연산자와 함께 호출되는 함수는 non-constructor가 아닌 constructor이어야 한다. | ||
|
||
### new.target | ||
|
||
생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 파스칼 케이스 컨벤션을 사용한다 하더라도 실수는 언제나 발생할 수 있다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# 18 - 함수와 일급 객체 | ||
|
||
### 일급 객체의 의미 | ||
|
||
: 함수를 객체와 동일하게 사용이 가능하다는 의미이다. | ||
|
||
일반 객체는 호출할 수 없지만 함수는 호출이 가능하다. 또한 함수 객체는 일반 객체에는 없는 함수 **고유의 프로퍼티**를 소유한다. | ||
|
||
### 일급 객체의 조건 | ||
|
||
1. 무명의 리터럴로 생성 가능. 즉, 런타임에서 생성이 가능. | ||
2. 변수나 자료 구조에 저장이 가능. | ||
3. 함수의 매개 변수에 전달이 가능. | ||
4. 함수의 반환값으로 사용이 가능. | ||
|
||
위를 만족하면 일급객체 → 자바스크립트 함수를 위를 모두 만족 | ||
|
||
# 18.2 함수 객체의 프로퍼티 | ||
|
||
함수는 객체이므로 프로퍼티를 가질 수 있다. | ||
|
||
## 18.2.1 arguments 프로퍼티 | ||
|
||
함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체 | ||
|
||
- 매개 변수를 확정할 수 없는 **가변 인자 함수** 구현에 유용. | ||
|
||
```tsx | ||
function sum() { | ||
let res = 0; | ||
|
||
// arguments 객체는 length 프로퍼티가 있는 유사 배열 객체이므로 for 문으로 순회할 수 있다. | ||
for (let i = 0; i < arguments.length; i++) { | ||
res += arguments[i]; | ||
} | ||
|
||
return res; | ||
} | ||
|
||
console.log(sum()); // 0 | ||
console.log(sum(1, 2)); // 3 | ||
console.log(sum(1, 2, 3)); // 6 | ||
``` | ||
|
||
## 18.2.2 caller 프로퍼티 | ||
|
||
ECMAScript 사양에 포함되지 않는 비표준 프로퍼티. | ||
|
||
```tsx | ||
function foo(func) { | ||
return func(); | ||
} | ||
|
||
function bar() { | ||
return 'caller : ' + bar.caller; | ||
} | ||
|
||
// 브라우저에서의 실행한 결과 | ||
console.log(foo(bar)); // caller : function foo(func) {...} | ||
console.log(bar()); // caller : null | ||
``` | ||
|
||
## 18.2.3 length 프로퍼티 | ||
|
||
함수를 정의할 때 선언한 매개변수의 개수. | ||
|
||
arguments 객체의 length 프로퍼티 : 인자 (argument)의 개수. | ||
|
||
함수 객체의 length 프로퍼티 : 매개변수 (parameter)의 개수. | ||
|
||
## 18.2.4 name 프로퍼티 | ||
|
||
함수 이름을 나타내며 ES6부터 정식 표준이 되었다. | ||
|
||
ES5에서는 빈 문자열을 값, ES6에서는 함수 객체를 가리키는 식별자를 값으로 갖는다. | ||
|
||
```jsx | ||
기명 함수 표현식 | ||
var namedFunc = function foo() {}; | ||
console.log(namedFunc.name); // foo | ||
|
||
// 익명 함수 표현식 | ||
var anonymousFunc = function() {}; | ||
// ES5: name 프로퍼티는 빈 문자열을 값으로 갖는다. | ||
// ES6: name 프로퍼티는 함수 객체를 가리키는 변수 이름을 값으로 갖는다. | ||
console.log(anonymousFunc.name); // anonymousFunc | ||
|
||
// 함수 선언문(Function declaration) | ||
function bar() {} | ||
console.log(bar.name); // bar | ||
``` | ||
|
||
## 18.2.5 `__proto__` 접근자 프로퍼티 | ||
|
||
`[[Prototype]]` 내부 슬롯이 가리키는 프로토타입 객체에 접근할 수 있는 접근자 프로퍼티. | ||
|
||
```jsx | ||
const obj = { a: 1 }; | ||
|
||
// 객체 리터럴 방식으로 생성한 객체의 프로토타입 객체는 Object.prototype이다. | ||
console.log(obj.__proto__ === Object.prototype); // true | ||
|
||
// 객체 리터럴 방식으로 생성한 객체는 프로토타입 객체인 Object.prototype의 프로퍼티를 상속받는다. | ||
// hasOwnProperty 메서드는 Object.prototype의 메서드다. | ||
console.log(obj.hasOwnProperty('a')); // true | ||
console.log(obj.hasOwnProperty('__proto__')); // false | ||
``` | ||
|
||
## prototype 프로퍼티 | ||
|
||
생성자 함수로 호출할 수 있는 constructor 만 소유할 수 있는 프로퍼티.non-constructor 에는 존재하지 않는다. | ||
|
||
```jsx | ||
|
||
(function () {}).hasOwnProperty('prototype'); // -> true | ||
|
||
({}).hasOwnProperty('prototype'); // -> false | ||
``` |