19.12 정적 프로퍼티/메서드
정적 프로퍼티/메서드 (static)
- 생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티/메서드
- 생성자 함수 객체가 소유한 프로퍼티/메서드
- 생성자 함수가 생성한 인스턴스로 참조/호출할 수 없다
- 생성자 함수가 생성한 인스턴스는 자신의 프로토타입 체인에 속한 객체의 프로퍼티/메서드에 접근할 수 있다
- 정적 프로퍼티/메서드는 인스턴스의 프로토타입 체인에 속한 객체의 프로퍼티/메서드가 아니므로 인스턴스에 접근 불가
//생성자 함수
function Person(name) {
this.name = name;
}
//프로토타입 메서드
Person.prototype.sayHello = function() {
console.log(`Hi! My name is ${this.name}`);
};
//정적 프로퍼티
Person.staticProp = 'static prop';
//정적 메서드
Person.staticMethod = function() {
console.log('staticMethod');
};
const me = new Person('Lee');
//생성자 함수에 추가한 정적 프로퍼티/메서드는 생성자 함수로 참조/호출
Person.staticMethod(); //staticMethod
//정적 프로퍼티/메서드는 생성자 함수가 생성한 인스턴스로 참조/호출할 수 있다.
//인스턴스로 참조/호출할 수 있는 프로퍼티/메서드는 프로토타입 체인 상에 존재해야 한다.
me.staticMethod(); //TypeError
- 인스턴스/프로토타입 메서드 내에서 this를 사용하지 않는다면 그 메서드는 정적 메서드로 변경할 수 있음
- 메서드 내에서 인스턴스를 참조할 필요가 없다면 정적 메서드로 변경하여도 동작
function Foo() {}
//프로토타입 메서드
//this를 참조하지 않는 프로토타입 메서드는 정적 메서드로 변경하여도 동일한 효과를 얻을 수 있다
Foo.prototype.x = function() {
console.log('x');
};
const foo = new Foo();
//프로토타입 메서드를 호출하려면 인스턴스를 생성해야 한다
foo.x(); //x
//정적 메서드
Foo.x = function() {
console.log('x');
};
//정적 메서드는 인스턴스를 생성하지 않아도 호출할 수 있다.
Foo.x(); //x
19.13 프로퍼티 존재 확인
19.13.1 in 연산자
- in 연산자는 객체 내에 특정 프로퍼티가 존재하는지 여부를 확인
/*
key: 프로퍼티 키를 나타내는 문자열
object: 객체로 평가되는 표현식
*/
key in object
const Person = {
name : 'Lee',
address : 'Seoul'
};
//Person 객체에 name 프로퍼티가 존재
console.log('name' in person); //true
//Person 객체에 address 프로퍼티가 존재
console.log('address' in person); //true
//Person 객체에 age 프로퍼티가 존재하지 않음
console.log('age' in person); //false
- 확인 대상 객체가 상속받은 모든 프로토타입의 프로퍼티를 확인
- in 연산자는 person 객체가 속한 프로토타입 체인 상에 존재하는 모든 프로토타입에서 toString을 검색
console.log('toString' in person); //true
- ES6에서는 Reflect.has 메서드를 사용 가능
const Person = { name: 'Lee'};
console.log(Reflect.has(Person,'name')); //true
console.log(Reflect.has(Person,'toString')); //true
19.13.2 Object.prototype.hasOwnProperty 메서드
Object.prototype.hasOwnProperty
- 인수로 전달받은 프로퍼티 키가 객체 고유의 프로퍼티 키인 경우에만 true를 반환하고
- 상속받은 프로토타입의 프로퍼티 키인 경우 false를 반환
console.log(person.hasOwnProperty('name')); //true
console.log(person.hasOwnProperty('age')); //false
console.log(person.hasOwnProperty('toString')); //false
19.14 프로퍼티 열거
19.14.1 for... in 문
- 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거
for (변수선언문 in 객체) {..}
- 순회 대상 객체의 프로퍼티 뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거
const Person = {
name : 'Lee',
address: 'Seoul'
};
//in 연산자는 객체가 상속받은 모든 프로토타입의 프로퍼티를 확인
console.log('toString' in Person); //true
//for..in문도 객체가 상속받은 모든 프로토타입의 프로퍼티를 열거
//하지만 toString와 같은 Object.prototype의 프로퍼티가 열거되지 않음
for(const key in Person) {
console.log(key + ':' + Person[key]);
}
//name:Lee address:Seoul
- for..in문은 프로퍼티 키가 심벌인 프로퍼티는 열거하지 않음
const sym = Symbol();
const obj = {
a:1,
[sym]:10
};
for(const key in obj) {
console.log(key + ':' + obj[key]); //a:1
}
- 상속받은 프로퍼티는 제외하고 객체 자신의 프로퍼티만 열거하려면 Object.prototype.hasOwnProperty 메서드를 사용하여 객체 자신의 프로퍼티인지 확인
const person = {
name:'Lee',
address:'Seoul',
__proto__: {age:20}
};
for(const key in person) {
//객체 자신의 프로퍼티인지 확인
if(!person.hasOwnProperty(key)) continue;
console.log(key + ":" + person[key]);
}
//name:Lee
//address:Seoul
19.14.2 Object.keys/values/entries 메서드
- 객체 자신의 고유 프로퍼티만 열거하기 위해서는 Obejct.keys/values/entries 메서드를 사용하는 것을 권장
Object.keys 메서드
- 객체 자신의 열거가능한 프로퍼티 키를 배열로 반환
const person = {
name:'Lee',
address:'Seoul',
__proto__: {age:20}
};
console.log(Object.keys(person)); //[ 'name', 'address' ]
Object.values 메서드
- 객체 자신의 열거 가능한 프로퍼티 값을 배열로 반환
console.log(Object.values(person)); //[ 'Lee', 'Seoul' ]
Object.entries 메서드
- 객체 자신의 열거 가능한 프로퍼티 키와 값의 쌍의 배열을 배열에 담아 반환
console.log(Object.entries(person)); //[ [ 'name', 'Lee' ], [ 'address', 'Seoul' ] ]
Object.entries(person).forEach(([key,value]) => console.log(key, value));
//name Lee
//address Seoul
'JavaScript' 카테고리의 다른 글
[Deep dive] 21장 빌트인 객체 (0) | 2023.08.11 |
---|---|
[Deep dive] 20장 strict mode (0) | 2023.08.11 |
[Deep dive] 19장 프로토타입(2) (0) | 2023.08.10 |
[Deep dive] 19장 프로토타입 (1) (0) | 2023.08.10 |
[Deep dive] 18장 함수와 일급객체 (0) | 2023.08.10 |