whatisthis?

javaScript. (16) Object 객체 본문

WEB STUDY/JAVASCRIPT

javaScript. (16) Object 객체

thisisyjin 2022. 1. 28. 13:49

Object 객체

-  object 자체도 객체이다. (모든 객체의 최종 prototype임)

 

- 객체의 prototype 확인

>> 이미 구현된 객체의  prototype을 확인하려면, __proto__를 사용.

 

 

Math.__proto__;       // Object { ... }

예를 들어 Math 객체의 prototype을 확인해보면 Object 객체가 나온다.

즉, 모든 객체의 prototype은 결국 Object 객체이다.

 


** 생성자로 만든 객체의 prototype의 prototype도 Object 객체가 됨.

function Person(name) { this.name = name; }
Person.prototype.sayHello = function() {
  console.log(this.name);
};

const yjin = new Person('yjin');
yjin.__proto__;      // { sayHello: function() }
yjin.__proto__.__proto__;     // Object { ... }

>> 그냥 prototype은 일반 객체 (안에 메서드가 있는) 이고,

그 일반 객체의 prototype이 Object 객체이다.

 

 

** 그렇다면, Object 객체의 prototype은?

Math.__proto__.__proto__;    // null

- Null 이다.

(Object 객체가 최종이기 떄문에)

 

 

모든 객체가 Object 객체로부터 상속을 받음. (즉, 모든 객체의 '부모'인 셈)

내가 해본것

constructor이 Object (생성자 함수)로 뜸.

그럼 Object 생성자로 Math를 만든 것인가?

 


Object 객체 Method

 

 

1) 객체.hasOwnProperty(속성명)

- 객체의 특정 속성이 상속받지 않은 속성인지 알려줌.

(즉, 자기자신의 속성이면 true / 부모 속성이거나 아예 속성이 아니면 false)

const obj = {
   example: 'yes'
};

obj.example;   // 'yes'
obj.hasOwnProperty('example');    // true
obj.toString;      // function String() { [native code] }
obj.hasOwnProperty('toString');     // false ㅡ 자신의 속성이 아님

 

2) 객체.isPrototypeOf(대상)

- 객체가 대상의 조상인지 알려줌.

const GrandParent = function() {};

const Parent = function() {};

Parent.prototype = new GrandParent();
Parent.prototype.constructor = Parent;



const Child = function() {};
Child.prototype = new Parent();
Child.prototype.constructor = Child;

const child = new Child();
Parent.prototype.isPrototypeOf(child);    // true
GrandParent.prototype.isPrototypeOf(child);   // true

 

내가 궁금해서 해본 것 🔻

Parent.prototype.isPrototypeOf(Child);
/// false

Parent.prototype.isPrototypeOf(Child.prototype);
/// true

 

- Parent.prototye은 GrandParent 생성자이다.

 

 

child와 Child의 차이

- Child는 일반 함수이다.

- child는 Child{}이다. 즉, 생성자함수 자체이다.

>> Child.prototype = new Parent()를 해줬으므로 [[prototype]]은 Parent가 된다.

(즉, Parent 연산자로 만든 Child.prototype)

 

 

__proto__로 프로토타입에 접근해본 결과

 

 

new Child (=child) = Child {} > Parent > GrandParent > Object

 

 

 

3) Object.getPrototypeOf(객체) / Object.setPrototypeOf(객체, prototype)

- 객체의 프로토타입을 조회 / 설정함.

Object.getPrototypeOf(child);  // Parent
Object.getPrototypeOf(new GrandParent());  // 빈 객체 { }
Object.setPrototypeOf(child, new Parent());

- child는 Child{}이므로

child의 prototype은 Parent이고,

 

new GrandParent()로 생성한 객체의 prototype은 grandParent 생성자이므로

그의 prototype은 Object가 된다.

 

 

4) instanceof

- 연산자임. (typeof와 마찬가지)

- 객체가 특정 생성자의 자식인지 조회 가능

child instanceof Parent;    // true
child instanceof GrandParent;     // true
객체   instanceof   생성자(함수)

 

 

 

5) 객체.propertyIsEnumerable(속성)

- 해당 속성(property)이 열거 가능한지 알려줌.

- 열거 가능이란?

>> for ... in 과 같은 반복문 안에서 사용 가능한지.

- 상속받은 속성 / 해당 객체의 속성이 아닌것은 제외됨 (즉, Own Property 중에서만)

 

 

💡 for ... in

-  상속된 열거 가능한 속성들을 포함하여

객체에서 문자열로 키가 지정모든 열거 가능한 속성에 대해 반복.

const object = { a: 1, b: 2, c: 3 };

for (const property in object) {
  console.log(`${property}: ${object[property]}`);
}

 

 

 

6) 객체.toString

- 객체를 console.log 했을때 결과가 안나오고 [object Object] 같이 나올 때

- 객체 내부적으로 toString 메서드가 호출된 결과.

- 문자열끼리 더할 때 주로 호출된다.

 

기본적으론 객체의 종류를 알려주고, 사용자가 임의로 변경 가능함.

 

const obj = {a: 'hi', b: 'yjin'};

obj.toString();   // [object Object]
Math.toString();   // [object Math]

obj.toString = function() {                // 임의로 변경
   return this.a + ' ' + this.b;
};

obj.toString();      // 'hi yjin';
obj + ' nice to meet you';    // 'hi yjin nice to meet you'

 

 

7) 객체.valueOf

 

- 객체의 기본 값을 의미.

- 숫자 계산을 할 때, 내부적으로 호출됨.

- toString과 같이 내부적 호출이므로 관리하기 어려움.

 

const obj = { a: 'hi', b: 'zero' };
obj.valueOf(); // { a: 'hi', b: 'zero' } ㅡ 기본값
obj + 5; // '[object Object]5' ㅡ 내부적으로 toString이 호출됨
obj.valueOf = function() {          // 임의로 바꿀 수 있음
  return 3;
}
obj + 5; // 8 <-- 내부적으로 valueOf가 호출됨
toString과 valueOf 모두
임의로 바꾸려면 함수의 return기능으로 바꾼다.

 

 

 

8) Object.create(prototype, 속성들)

- 객체를 생성하는 방법 중 하나.

const obj = {};      
//  Object.create(Object.prototype); 과 같음


const obj2 = Object.create(null, {
  a: {                           // prototype은 null이고, 속성들만 부여
    writable: true,
    configurable: false,
    value: 5,
  }
});

obj2.a; // 5 ㅡ value가 나옴

>> 속성 '들' 이므로 객체의 형태로 속성들을 부여했다. 

 

 

- 속성들 (properties)

writable / configurable / enumerable / get / set / value

 

 

** 지난번 객체 상속에서

Object.create()를 통해 상속받는 객체에게 프로토타입 객체를 전달했었다. (=주소를 건네줌)

Sedan.prototype = Object.create(Vehicle.prototype)

 

 

 

9) Object.defineProperties(객체, 속성들) / Object.defineProperty(객체, 속성, 설명)

- 객체의 속성을 자세하게 정의할 수 있음.

writable (할당 연산자로) 속성 변경 가능 Default :     false
configurable 속성 설명 변경 가능
enumerable for ... in에서 사용 가능 (열거)
get 속성값을 가져올때 value 관련
set 속성값을 설정할때
value 속성값

 

 

- writable은 속성값을 바꾸는 것은 막지만, 만약 속성값이 객체면 그 안의 속성을 바꾸는 것은 막지 못함.

>> 전체적으로 변경을 막기 위한 Object.freeze 메서드도 존재.

 

 

const obj = {};

Object.defineProperties(obj, {
  a: {
    value: 5,
    writable: false,
    enumerable: true,
  },
  
  b: {
    get: function() {
      return 'zero';
    },
    set: function(value) {
      console.log(this, value);
      this.a = value;
    },
    enumerable: false,
    configurable: false,
  },
});

obj.a;	 	// 5
obj.b; 		// 'zero'  ㅡ get에 의해
obj.a = 10;
obj.a; 		// writable이 false라 그대로 5

for (var key in obj) {
  console.log(key); 	// b의 enumerable이 false이니까 a만 log됨  ㅡ a는 enumerable이 true
}

obj.b = 15;		 // 15로 설정되는 대신 set의 내용이 실행됨. set의 value는 15
obj.a; 		// this.a = value로 인해 15로 바뀌어야 하나 writable이 false라 무시됨
obj.b;		 // 그대로 'zero'

Object.defineProperty(obj, 'b', {
  value: 5
}); 		// Uncaught TypeError: Cannot redefine property: b ㅡ configurable이 false라

 

 

💡 defineProperties   vs.  defineProperty

Object.defineProperties(객체, 속성들) 통채로 바꾸거나 생성함.
Object.defineProperty(객체, 바꿀 속성명, 설명) 이미 존재하는 속성 하나를 이름을 지정해
바꾸거나 새로 정의함.

 

( 객체명, { a : {value : 5,  writable : true ... } , b : { get: function() {}, ... } ... } )

 

** 속성들(properties)

>> { a : {value : 5,  writable : true ... } , b : { get: function() {}, ... } ... } 

즉, a와 b (를 포함한 전체 객체.) / a 하나가 속성 하나임

 

** 설명(descriptor) = 속성을 기술하는 객체.

>> {value : 5,  writable : true ... } 

선택적 키를 공유 - configurable / enumerable / value / writable / get / set

 

 

10) Object.getOwnPropertyDescriptor(객체, 속성)

- 속성의 설명값(descriptor)을 불러옴.

Object.getOwnPropertyDescriptor(obj, 'b');    // b 속성에 해당하는 설명값 불러옴

// { enumerable : false, configurable : false, get : function() {}, set : function(value) {} }

 

 

11) Object.freeze  / Object.seal  / Object.preventExtensions

- writable을 false로 해도, value가 객체이면 객체의 속성이 바뀌는 것을 막을 수 없음.

>> freeze를 사용하면 객체 전체를 못바꾸게 고정시킴.

(값도 못바꾸고 / 속성 추가 및 제거 / 설명 변경 등 다 안됨.)

 

Object.freeze 

값 변경 / 속성 추가,제거 / 설명 변경

Object.seal

속성 추가,제거  /  설명 변경 ❌  
writable : true이면 값 변경은

Object.preventExtensions

속성 추가 ❌
속성 제거 / 값 변경 / 설명 변경은 ⭕

 

12) Object.isFrozen  /  Object.isSealed  / Object.isExtensible

- 객체가 freeze 되었는지 / seal 되었는지 / preventExtension 상태인지 확인.

 

 

 

13) Object.keys

- 객체의 속성명을 모두 가져와 배열로 반환.

Object.keys(obj);      // ['a', 'c']
// 'b'는 enumerable = false이므로 ❌

❗❗ 단, enumerable(열거가능)이 false면 제외한다.

 

 

14) typeof

- 식의 type을 알려줌.

- 배열 null도 Object로 표현됨.

>> 배열을 구분하려면 Array.isArray를 사용 / null을 구분하려면 === 연산자 사용해서 구분.

 

** null은 객체가 아닌 기본타입이며, 이는 자바스크립트 초기의 오류사항임.

(아마, typeof연산에서 null을 체크하는 코드가 빠진듯?)

 

 

참고로,  Number, Object, Boolean, String 등은 typeof를 하면 function으로 나온다!

+) typeof NaN = number이지만 / NaN == number은 false이다.

 

 

 

15) delete

- 객체 내의 속성을 지울 수 있음.

- 성공시 true / 실패시  false 반환.

>>> configurable(설명 변경가능)이 false이거나 isFreeze가 true면 실패함.

 


REFERENCE

 

https://www.zerocho.com/category/JavaScript/post/573dbc9370ba9c603052cc9a

 

(JavaScript) Object 객체

안녕하세요. 중급 강좌 첫 번째 시간이네요! 자바스크립트는 객체 지향 프로그래밍 언어이니만큼 Object 객체에 대해 알아보겠습니다. Object가 객체이니까 Object 객체는 객체 객체이겠네요! 사실 Ob

www.zerocho.com

 

이 포스팅은 zerocho님의 javascript 강의를 보고 작성한 글입니다.

공부+기록 용으로 작성한 것이며, 자세한 것은 위 포스팅을 참고하세요!