16장 프로퍼티 어트리뷰트
16.1 내부 슬롯과 내부 메서드
내부 슬롯 internal slot
자바스크립트 엔진의 구현 알고리즘을 설명하기위해 ECMAScript 사양에서 사용하는 의사 프로퍼티(pseudo property)
내부 메서드 internal method
자바스크립트 엔진의 구현 알고리즘을 설명하기위해 ECMAScript 사양에서 사용하는 의사 메서드(pseudo method)
내부 슬롯과 내부 메서드는 ECMAScript 사양에 정의된 대로 구현되어 자바스크립트 엔진에서 실제로 동작한다.
하지만 개발자가 직접 접근할 수 있도록 외부로 공개된 객체의 프로퍼티는 아니다.
원칙적으로 자바스크립트는 내부 슬롯과 내부 메서드에 직접적으로 접근하거나 호출할 수 있는 방법을 제공하지 않는다.
예) [[Prototype]]
모든 객체는 [[Prototype]] 이라는 내부 슬롯을 가진다.
내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 원칙적으로 직접 접근할 수 없지만, [[Prototype]] 내부 슬롯은,
__proty__를 통해 간접적으로 접근 가능
const o = {};
o.toString; // 사용 가능하다. 빈 객체인데 왜..?
// 내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 직접 접근할 수 없다.
o.[[Prototype]]; // Uncaught SyntaxError
// 단, 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공한다.
// 프로토타입에게 상속받은 메서드를 확인할 수 있다.
o.__proto__ // Object.prototype
o는 빈 객체임에도 불구하고 toString이라는 메서드를 가지고 있었다.
즉, toString은 상속받은 것이다.
객체 o의 상위 객체가 존재하는데, 그것을 프로토타입이라고 부르고 그에게서 상속받은 것!
프로토타입은 Object.prototype 이다.
객체는 Object.prototype을 상속받아 사용할 수 있다.
모든 객체는 내부 슬롯 [[Prototype]] 을 가지지만 직접 접근할 수는 없다.
따라서 o.[[Prototype]] 는 사용이 불가능하지만
o.__proto__ 로 간접적으로 접근 가능하다.
하지만 o.__proto__가 좀 이상하게 생겼으니... Object.getPrototypeOf(o)를 대안으로 사용할 수 있다.
16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
자바스크립트 엔진은 프로퍼티를 생성할 때 *프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다.
*프로퍼티 상태 : 프로퍼티의 값(value), 값의 갱신 가능 여부(writable), 열거 가능 여부(enumerable), 재정의 가능 여부(configurable)
프로퍼티 어트리뷰트
자바스크립트 엔진이 관리하는 내부 상태 값(meta-property)인 내부 슬롯이다.
[[value]], [[Writable]], [[Enumerable]], [[Configurable]]
따라서 프로퍼티 어트리뷰트에 직접 접근할 수는 없지만
Object.getOwnPropertyDescriptor 메서드를 사용해 간접적으로 확인할 수 있다.
const person = {
name: 'Lee'
};
// 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환한다.
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// 프로퍼티 디스크립터 객체: { value: 'Lee', writable: true, enumerable: true, configurable: true }
Object.getOwnPropertyDescriptor
하나의 프로퍼티 어트리뷰트 정보를 제공한다.
하나의 프로퍼티 디스크립터 객체를 반환한다.
Object.getOwnPropertyDescriptor(obj, "key");
// { value: , writable: boolean, enumerable: boolean, configurable: boolean }
프로퍼티 디스크립터 객체
- Object.getOwnPropertyDescriptor 메서드를 호출하면 프로퍼티 디스크립터 객체를 반환한다.
- 프로퍼티 디스크립터 객체는 프로퍼티 어트리뷰트 정보를 제공한다.
Object.getOwnPropertyDescriptors
모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.
const person = { name: 'Lee' };
// 프로퍼티 동적 생성
person.age = 20;
// 모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.
console.log(Object.getOwnPropertyDescriptors(person));
/*
{
name: {value: "Lee", writable: true, enumerable: true, configurable: true},
age: {value: 20, writable: true, enumerable: true, configurable: true}
}
*/
16.3 데이터 프로퍼티와 접근자 프로퍼티
프로퍼티는 두 가지로 구분할 수 있다.
데이터 프로퍼티 data property
키와 값으로 구성된 일반적인 프로퍼티
지금까지 살펴본 모든 프로퍼티는 데이터 프로퍼티
[[Value]] 내부 슬롯이 있다.
접근자 프로퍼티 accessor property
자체적으로 값을 가지지 않고 다른 데이터 프로퍼티 값을 읽거나 저장할 때 호출되는 접근자 함수 accessor function으로 구성된 프로퍼티
[[Value]] 내부 슬롯이 없다.
메서드가 아니고 프로퍼티다.
따라서 접근자 프로퍼티를 사용할 때는 프로퍼티 키를 () 없이 사용한다.
16.3.1 데이터 프로퍼티
데이터 프로퍼티는 다음과 같은 프로퍼티 어트리뷰트를 갖는다.
이 프로퍼티 어트리뷰트는 자바스크립트 엔진이 프로퍼티를 생서앟ㄹ 때 기본값으로 자동 정의된다.
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
[[Value]] | value | 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값 |
[[Writable]] | writable | 프로퍼티 값의 변경 가능 여부를 나타내며 불리언 값을 가짐 |
[[Enumerable]] | enumerable | 프로퍼티의 열거 가능 여부를 나타내며 불리언 값을 가짐 |
[[Configurable]] | configurable | 프로퍼티의 재정의 가능 여부를 나타내며 불리언 밧을 가짐 |
16.3.2 접근자 프로퍼티
자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
프로퍼티 어트리뷰트 | 프로퍼티 디스크립터 객체의 프로퍼티 | 설명 |
[[Get]] | get | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 |
[[Set]] | set | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 |
[[Enumerable]] | enumerable | 프로퍼티의 열거 가능 여부를 나타내며 불리언 값을 가짐 |
[[Configurable]] | configurable | 프로퍼티의 재정의 가능 여부를 나타내며 불리언 밧을 가짐 |
접근자 함수는 getter/ setter 함수라고도 부른다.
getter setter 함수를 모두 정의할 수도 있고 하나만 정의할 수도 있다.
const person = {
// 데이터 프로퍼티
firstName: 'Ungmo',
lastName: 'Lee',
// fullName은 접근자 함수로 구성된 접근자 프로퍼티다.
// getter 함수
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
// setter 함수
set fullName(name) {
// 배열 디스트럭처링 할당: "31.1 배열 디스트럭처링 할당" 참고
[this.firstName, this.lastName] = name.split(' ');
}
};
// 데이터 프로퍼티를 통한 프로퍼티 값의 참조.
console.log(person.firstName + ' ' + person.lastName); // Ungmo Lee
// 접근자 프로퍼티를 통한 프로퍼티 값의 저장
// 접근자 프로퍼티 fullName에 값을 저장하면 setter 함수가 호출된다.
person.fullName = 'Heegun Lee';
console.log(person);
// {firstName: "Heegun", lastName: "Lee"}
// 접근자 프로퍼티를 통한 프로퍼티 값의 참조
// 접근자 프로퍼티 fullName에 접근하면 getter 함수가 호출된다.
console.log(person.fullName); // Heegun Lee
// firstName은 데이터 프로퍼티다.
// 데이터 프로퍼티는 [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]
// 프로퍼티 어트리뷰트를 갖는다.
let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log(descriptor);
// {value: "Heegun", writable: true, enumerable: true, configurable: true}
// fullName은 접근자 프로퍼티다.
// 접근자 프로퍼티는 [[Get]], [[Set]], [[Enumerable]], [[Configurable]]
// 프로퍼티 어트리뷰트를 갖는다.
descriptor = Object.getOwnPropertyDescriptor(person, 'fullName');
console.log(descriptor);
// {get: ƒ, set: ƒ, enumerable: true, configurable: true}
점근자 프로퍼티로 프로퍼티 값에 접근시(읽을 때) 동작
- 프로퍼티 키가 유효한지 확인한다. 프로퍼티 키는 문자열 또는 심벌이여야한다.
- 프로토타입 체인에서 프로퍼티를 검색한다.
- 검색된 프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인한다.
- 접근자 프로퍼티라면 프로퍼티 어트리뷰트 [[Get]]의 값, 즉 getter 함수를 호출하여 그 결과를 반환한다.
- 프로토타입 prototype
어떤 객체의 상위(부모) 객체의 역할을 하는 객체이다.
프로토타입은 하위(자식) 객체에게 자신의 프로퍼티와 메서드를 상속한다.
- 프로터타입 체인
프로토타입이 단방향 링크드 리스트 형태로 연결되어 있는 상속 구조를 말한다.
접근자 프로퍼티와 데이터 프로퍼티 구별
// 일반 객체의 __proto__는 접근자 프로퍼티다.
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
// {get: ƒ, set: ƒ, enumerable: false, configurable: true}
// 함수 객체의 prototype은 데이터 프로퍼티다.
Object.getOwnPropertyDescriptor(function() {}, 'prototype');
// {value: {...}, writable: true, enumerable: false, configurable: false}
16.4 프로퍼티 정의
프로퍼티 정의란
새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의 하는 것
Object.defineProperty
프로퍼티의 어트리뷰트를 정의할 수 있다.
인수로 객체의 잠조, 데이터 프로퍼티의 키인 문자열, 프로퍼티 디스크립터 객체 를 전달한다.
const person = {};
// 데이터 프로퍼티 정의
Object.defineProperty(person, 'firstName', {
value: 'Ungmo',
writable: true,
enumerable: true,
configurable: true
});
Object.defineProperty(person, 'lastName', { value: 'Lee' });
object.defineProperty 메소드로 프로퍼티를 정의할 때,
프로퍼티 디스크립터 객체의 프로퍼티를 일부 생략할 수 있다.
생략된 어트리뷰트는 다음과 같이 기본값이 적용된다.
프로퍼티 디스크립터 객체의 프로퍼티 | 대응하는 프로퍼티 어트리뷰트 | 생략했을 때의 기본값 |
value | [[Value]] | undefined |
get | [[Get]] | |
set | [[Set]] | |
writable | [[Writable]] | false |
enumerable | [[Enumerable]] | |
configurable | [[Configurable]] |
Object.defineProperties
여러 개의 프로퍼티를 한 번에 정의할 수 있다.
const person = {};
Object.defineProperties(person, {
// 데이터 프로퍼티 정의
firstName: { value: 'Ungmo', writable: true, enumerable: true, configurable: true },
lastName: { value: 'Lee', writable: true, enumerable: true, configurable: true },
// 접근자 프로퍼티 정의
fullName: {
// getter 함수
get() {
return `${this.firstName} ${this.lastName}`;
},
// setter 함수
set(name) {
[this.firstName, this.lastName] = name.split(' ');
},
enumerable: true,
configurable: true
}
});
person.fullName = 'Heegun Lee';
console.log(person);
// {firstName: "Heegun", lastName: "Lee"}
16.5 객체 변경 방지
프로퍼티를 추가하거나 삭제할 수 있고,
프로퍼티 값을 갱신할 수 있고,
Object.defineProperty, Object.defineProperties 메서드를 사용하여 프로퍼티 어트리뷰트를 재정의할 수 있다.
객체 변경을 방지하는 다양한 메서드
구분 | 메서드 | 프로퍼티 추가 | 프로퍼티 삭제 | 프로퍼티 값 읽기 | 프로퍼티 값 쓰기 | 프로퍼티 어트리뷰트 재정의 | 확인 메서드 |
객체 확장 금지 | Obejct.preventExtensions | X | O | O | O | O | Object.isExtensible |
객체 밀봉 | Object.seal | X | X | O | O | X | Object.isSealed |
객체 동결 | Obejct.freeze | X | X | O | X | X | Object.isFrozen |
Object.freeze를 가장 많이 사용한다.
Object.preventExtension | 어트리뷰트 전부 True / 읽기 쓰기 삭제 |
Objec.seal | configurable 만 false / 읽기 쓰기 |
Object.freeze | enumerable 만 true / 읽기 |
16.5.4 불변 객체
앞에서 살펴본 변경 방지 메서드는 얕은 변경 방지 (shallow only)로
직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 주지 못한다.
따라서 재귀를 사용해서 중첩된 객체까지 동결해야함.
불변 객체
중첩 객체 까지 동결해서 변경이 불가능한 읽기 전용의 불변 객체
17장 생성자 함수에 의한 객체 생성
17.1 Object 생성자 함수
new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환함.
근데 쓰지말자.. 그냥 리터럴쓰자.
생성자 함수 counstructor
new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수
생성자 함수에 의해 생성된 객체를 인스턴스 instance라 한다.
생성자 함수 종류
String, Number, Boolean, Function, Array, Date, RegExp, Promise...
17.2 생성자 함수
언제 생성자 함수를 쓰고, 언제 객체 리터럴을 사용하는가? => 질문으로 나오기 좋다.
객체 리터럴에 의한 객체 생성 방식은 단 하나의 객체만 생성하기 때문에,
동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 비효율적임.
17.2.2 생성자 함수에 의한 객체 생성 방식의 장점
프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성
// 생성자 함수
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// 인스턴스의 생성
const circle1 = new Circle(5); // 반지름이 5인 Circle 객체를 생성
const circle2 = new Circle(10); // 반지름이 10인 Circle 객체를 생성
console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20
this
this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수다.
함수 호출 방식에 따라 동적으로 결정됨
함수 호출 방식 | this가 가리키는 값( this 바인딩) |
일반 함수로 호출 | 전역 객체 |
메서드로 호출 | 메서드를 호출한 객체(마침표 앞의 객체) |
생성자 함수로서 호출 | 생성자 함수가 미래에 생성할 인스턴스 |
- new + 함수 식별자 : 생성자 함수
- 함수 식별자 : 일반 함수
new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작
17.2.3 생성자 함수의 인스턴스 생성 과정
생성자 함수의 역할
- 프로퍼티 구조가 동일한 인스터스를 생성하기 위해 템플릿으로 동작하여 인스턴스를 생성
- 생성된 인스턴스를 초기화(인스턴스 프로퍼티 추가 및 초기값 할당)
// 생성자 함수
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// 인스턴스의 생성
const circle1 = new Circle(5); // 반지름이 5인 Circle 객체를 생성
1. 인스턴스 생성과 this 바인딩
암묵적으로 빈 객체를 생성하고 빈 객체, 즉 인스턴스는 this에 바인딩된다.
생성자 함수 내부의 this가 생성자 함수가 생성할 인스턴스를 가리키는 이유는 this 바인딩 때문이다.
함수 몸체의 코드가 한 줄씩 실행되는 런타임 이전에 실행된다.
*바인딩: 식별자와 값을 연결하는 과정. 변수 선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩하는 것이다.
// 생성자 함수
function Circle(radius) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
console.log(this); // Circle {}
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
2. 인스턴스 초기화
생성자 함수에 기술되어 있는 코드가 한 줄씩 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다.
즉, this에 바인딩 되어 있는 인스턴스에 프로퍼티나 메서드를 추가하고
생성자 함수가 인수로 전달받은 초기값을 인스턴스 프로퍼티에 할당하여 초기화하거나 고정값을 할당한다.
// 생성자 함수
function Circle(radius) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
3. 인스턴스 반환
- 생성자 함수 내부의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
// 생성자 함수
function Circle(radius) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
// 3-1. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}
// 인스턴스의 생성. Circle 생성자 함수는 암묵적으로 this를 반환한다.
const circle1 = new Circle(5);
console.log(circle); // Circle {radius: 1, getDiameter: f}
- 명시적으로 다른 객체을 반환하면 this는 무시되고 명시한 객체가 반환된다.
// 생성자 함수
function Circle(radius) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
// 3-2. 명시적으로 객체를 반환하면, 암묵적인 this반환이 무시된다.
return {};
}
// 인스턴스의 생성. Circle 생성자 함수는 명시적으로 반환한 객체를 반환한다.
const circle1 = new Circle(5);
console.log(circle); // {}
- 명시적으로 원시 값을 반환하면, 원시 값 반환은 무시되고 암묵적으로 this가 반환된다.
// 생성자 함수
function Circle(radius) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩 된다.
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
// 3-3. 명시적으로 원시 값을 반환하면, 원시 값은 무시되고 암묵적으로 this가 반환된다.
return {};
}
// 인스턴스의 생성. Circle 생성자 함수는 암묵적으로 this를 반환한다.
const circle1 = new Circle(5);
console.log(circle); // Circle {radius: 1, getDiameter: f}
17.2.4 내부 메서드 [[Call]], [[Construct]]
함수 선언문, 함수 표현식으로 정의한 함수는
- 일반적인 함수로서 호출 가능
- 생성자 함수로서 호출 가능
생성자 함수로서 호출한다는 것은, new연산자와 함께 호출하여 객체를 생성하는 것.
함수 객체는 일반 객체와 동일하게 동작할 수 있다.
일반 객체가 가지고 있는 내부 슬롯, 내부 메서드 모두 가지고 있기 때문이다.
// 함수는 객체다.
function foo() {}
// 함수는 객체이므로 프로퍼티를 소유할 수 있다.
foo.prop = 10;
// 함수는 객체이므로 메서드를 소유할 수 있다.
foo.method = function () {
console.log(this.prop);
};
foo.method(); // 10
일반 객체와 함수 객체의 차이점
일반 객체는 호출할 수 없지만, 함수는 호출할 수 있다.
함수 객체는
일반 객체가 가지는 내부슬롯, 내부 메서드 + 함수 객체만을 위한 내부 슬롯, 내부 메서드
함수 객체의...
- 내부 슬롯 : *[[Environment]]. [[FormalParameters]]
- 내부 메서드 : [[Call]], [[Construct]]
*[[Environment]]는 상위 스코프의 참조.
렉시컬 스코프는 함수가 호출되는 위치가 아니라, 함수의 정의 위치에 따라 상위 스코프를 결정하는 것
일반 함수와 생성자 함수 차이점
일반 함수로서 호출되면 함수 객체의 내부 메서드 [[Call]] 가 호출된다
생성자 함수로 호출되면 내부 메서드 [[Construct]] 가 호출된다.
함수 객체의 특징
함수 객체는 반드시 callable이여야한다. 모든 함수 객체는 내부 메서드 [[Call]]을 가진다.
하지만 함수 객체는 constructor 일 수도 있고, non-constructor 일 수도 있다.
17.2.5 constructor와 non-constructor의 구분
- constructor : 생성자 함수로 사용 가능
함수 선언문, 함수 표현식, 클래스(클래스도 함수)
[[Call]], [[Construct]] 존재
new 연산자를 사용하여 호출할 수 있다.
- non-constructor : 생성자 함수로 사용 불가
메서드(ES6 메서드 축약 표현), 화살표 함수
[[Call]]는 있지만, [[Construct]]가 없다.
// 메서드 (축약표현)
const obj = {
x() {}
};
new obj.x(); // TypeError: obj.x is not a constructor
// 화살표 함수
const arrow = () => {};
new arrow(); // TypeError: arrow is not a constructor
17.2.7 new.target
new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가리킨다.
new 연산자 없이 일반함수로 호출된 함수 내부의 new.target은 undefined다.
// 생성자 함수
function Circle(radius) {
// 이 함수가 new 연산자와 함께 호출되지 않았다면 new.target === undefined
if(!new.target){
return new Circle(radius);
}
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// 인스턴스의 생성
const circle1 = Circle(5); // 반지름이 5인 Circle 객체를 생성
Built in 생성자 함수
Object, String, Number, Boolean, Function, Array, Date, RegExp
는 new 연산자와 함께 호출되었는지를 확인한 후 적절한 값을 반환한다.
String, Number, Boolean는
- new 연산자와 함께 호출 하하면 String, Number, Boolean객체를 반환
- new 연산자 없이 호출하면 데이터 타입을 변환
18장 함수와 일급 객체
자바스크립트에서 함수는 일급 객체다.
일급 객체는 다음과 같은 조건을 만족한다.
- 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다
- 변수나 자료구조(객체, 배열)에 저장할 수 있다.
- 함수의 매개 변수에 전달할 수 있다
- 함수의 반환값으로 사용할 수 있다
함수는 객체지만 일반 객체와 차이점이 있다.
일반 객체는 호출할 수 없지만, 함수 객체는 호출할 수 있다.
또한 함수 객체는 일반 객체에 없는 함수 고유의 프로퍼티를 소유한다.
18.2 함수 객체의 프로퍼티
Object.getOwnPropertyDescriptors 메서드로도 확인 가능하다.
함수 객체의 데이터 프로퍼티
argument, caller, length, name, prototype
'JavaScript > JavaScript 예복습' 카테고리의 다른 글
JavaScript 예습 | 27장 배열 (0) | 2021.09.26 |
---|---|
JavaScript 예습 | 19~21장 (0) | 2021.09.16 |
JavaScript 예습 | [deep dive] 13 ~ 15장 (0) | 2021.09.12 |
JavaScript 예습 | [deep dive] 10 ~ 12장 (0) | 2021.09.09 |
JavaScript 예습 | [deep dive] 6장~9장 (0) | 2021.09.07 |