JAVASCRIPT - 7. 객체

yeon·2022년 12월 12일

자바스크립트(ES6)

목록 보기
7/7

업로드중..


객체 생성하기

  1. 객체 리터럴로 생성하는 방법
  2. 생성자로 생성하는 방법
  3. Object.create로 생성하는 방법

// 1
var card = { suit: "하트", rank: "A" };

// 2
function Card(suit, rank){
 	this.suit = suit;
  	this.rank = rank;
}

// 3
var card = Object.create(Object.prototype,{
  suit: {
    value: "하트",
    writable: true,
    enumerable: true,
    configurable: true
  },
  rank{
  	value: "A",
  	writable: true,
	enumerable: true,
    configurable: true
  }
});

프로토타입

생성자 안에서 메서드를 정의하는 방식의 문제점

생성자 안에서 this 뒤에 메서드를 정의하면 그 생성자로 생성한 모든 인스턴스에 똑같은 메서드가 추가된다. 메서드를 포함한 생성자로 인스턴스를 여러 개 생성하면 같은 작업을 하는 메서드를 인스턴스 개수만큼 생성하게 되며 결과적으로 그만큼 메모리를 소비하게 된다.
→ 프로토타입 객체에 메서드를 정의하는 방식으로 해결


function Circle(center, radius){
  this.center = center;
  this.radius = radius;
  this.area = function(){
    return  Math.PI*this.radius*this.radius;
  };
}
var c1 = new Circle({x:0, y:0}, 2.0);
var c2 = new Circle({x:0, y:1}, 3.0);
var c3 = new Circle({x:1, y:0}, 1.0);

프로토타입 객체

함수의 prototype 프로퍼티가 가르키는 객체를 그 함수의 프로토타입 객체라 한다.
prototype 프로퍼티는 기본적으로 빈 객체를 가르킨다.


function F(){};
console.log(F.prototype);	// Object {}



프로토타입 객체의 프로퍼티는 생성자로 생성한 인스턴스에서 그 인스턴스의 프로퍼티처럼 사용할 수 있다. (상속)
프로토타입 객체의 프로퍼티는 읽기만 가능하고 수정이 불가능하다.


F.prototype.prop = "prototype value";
var obj = new F();
console.log(obj.prop);  // prototype value

obj.prop = "instance value";
console.log(obj.prop);  // instance value
console.log(F.prototype.prop);  // prototype value


프로토타입 상속

프로토타입 체인

내부 프로퍼티 [[Prototype]]

모든 객체는 내부 프로퍼티 [[Prototype]]을 가지고 있다.
ES6부터는 __proto__프로퍼티에 [[Prototype]]의 값이 저장된다.


var obj = {};
console.log(obj.__proto__);	// Object {}



프로토타입 체인

✔️ 객체의 __proto__ 프로퍼티는 그 객체에게 상속을 해 준 부모 객체를 가리킨다.
✔️ 객체는 __proto__ 프로퍼티가 가리키는 부모 객체의 프로퍼티를 사용할 수 있다.
* 실제 프로그래밍할 때는 __proto__ 프로퍼티 값을 직접 입력해서 상속하지 않는다.


var objA = {
  name: "Tom",
  sayHello: function(){console.log("Hello! "+this.name);}
};
var objB = {
  name: "Huck"
}; 
objB.__proto__ = objA;
var objC = {};
objC.__proto__ = objB;
objC.sayHello();  // "Hello! Huck"



일반적인 프로토타입 상속

  • 생성자로 객체를 생성할 때 생성자의 prototype 프로퍼티에 추가하는 방법
  • Object.create 메서드로 상속을 받을 프로토타입을 지정하여 객체를 생성하는 방법

프로토타입 가져오기

객체의 프로토타입은 Object.getPrototypeOf 메서드로 가져올 수 있다.
ES6부터 Object.setPrototypeOf 메서드를 이용해 객체의 프로토타입을 설정할 수 있다.


function F(){}
var obj = new F();
console.log(Object.getPrototypeOf(obj));	// Object{}



프로토타입 객체의 프로퍼티

?????

프로토타입 확인

instanceof 연산자

지정한 객체의 프로토타입 체인에 지정한 생성자의 프로토타입 객체가 포함되어 있는지 판정한다. 논리값을 반환하는 이항연산자이다.

객체 instanceof 생성자


function F(){};
var obj = new F();
console.log(obj instanceof F);  // true
console.log(obj instanceof Object); // true
console.log(obj instanceof Date); //false

instanceof 연산자가 확인하는 것은 그 인스턴스가 해당 생성자로 생성되었는지 여부가 아니라 인스턴스가 생성자의 프로토타입 객체를 상속받았는지 확인한다.


isPrototypeOf 메서드

isPrototypeOf 메서드는 특정 객체가 다른 객체의 프로토타입 체인에 포함되어 있는지 판정한다.

프로토타입객체.isPrototype(객체)


function F(){};
var obj = new F();
console.log(F.prototype.isPrototypeOf(obj));  // true
console.log(Object.prototype.isPrototypeOf(obj));  // true
console.log(Date.prototype.isPrototypeOf(obj));  // false

Object.prototype

Object.prototype의 메서드는 모든 내장 객체로 전파되며 모든 인스턴스에서 사용할 수 있다.

메서드 이름설명
hasOwnProperty(key)호출한 객체가 문자열 key를 이름으로 가진
프로퍼티를 소유하는지 뜻하는 논리값으로 반환한다.
isPrototypeOf(obj)호출한 객체가 인수 obj에 지정한 객체의 프로토타입인지를
뜻하는 논리값을 반환한다.
propertyIs
Enumerable(key)
호출한 객체가 문자열 key를 이름으로 가진 프로퍼티를 열거할 수 있는지를
뜻하는 논리값을 반환한다.
이 메서드를 호출한 객체가 소유한 프로퍼티만 판정하며
프로토타입의 프로퍼티는 판정하지 않는다.
toLocalString()toString 메서드와 같다.
valueOf()호출한 객체의 원시값을 반환한다.



접근자 프로퍼티

  • 데이터 프로퍼티 : 값을 저장하기 위한 프로퍼티
  • 접근자 프로퍼티 : 값이 없음. 프로퍼니를 읽거나 쓸 때 호출하는 함수를 값 대신에 지정할 수 있는 프로퍼티

접근자 프로퍼티

✔️ 접근자란 객체 지향 프로그래밍에서 객체가 가진 프로퍼티 값을 객체 바깥에서 읽거나 쓸 수 있도록 제공하는 메서드
✔️ 데이터를 부적절하게 변경하는 것을 막고 특정 데이터를 외부로부터 숨길 수 있고 외부에서 데이터를 읽으려고 시도할 때 적절한 값으로 가공해 넘길 수 있다.
✔️ delete 연산자로 삭제할 수 있다.


// getter, setter 함수 예제
var person = {
  _name: "Tom",
  get name(){
    return this._name;
  },
  set name(value){
    var str = value.charAt(0).toUpperCase()+value.substring(1);
    this._name = str;
  }
};
console.log(person.name); // Tom
person.name = "huck"; // 접근자 프로티에 값을 대입한다.
console.log(person.name)  // Huck 


// 삭제시 delete 연산자 사용
delete person.name;


데이터의 캡슐화

접근자 프로퍼티를 이용해 데이터 프로퍼티를 직접 읽고 쓸 수 있다.
즉시 실행 함수로 클로저를 생성하면 데이터를 객체 외부에서 읽고 쓸 수 없도록 숨기고 접근자 프로퍼티만 읽고 쓰도록 만들 수 있다.


var person = (function(){
    var _name = "Tom";  // 프라이빗 함수
    return{
      get name(){
        return _name;
      },
      set name(value){
        var str = value.charAt(0).toUpperCase() + value.substring(1);
        _name = str;
      }
    };
})();
console.log(person.name); // Tom
person.name = "huck";  // 접근자 프로퍼티에 값을 대입한다.
console.log(person.name); // Huck

// 변수 _name은 즉시 실행 함수의 지역 변수이므로 함수 바깥에서 읽거나 쓸 수 없다. 




프로퍼티의 속성

  • 쓰기 가능 (writable)
    프로퍼티에 쓰기가 가능한지 뜻하는 속성
    속성값이 true면 프로퍼티 값을 수정할 수 있다.

  • 열거 가능 (enumerable)
    프로퍼티가 for/in 문이나 Object.keys 등의 반복문으로 찾을 수 있는 대상인지를 (열거 가능) 뜻하는 속성

  • 재정의 가능 (configurable)
    프로퍼티의 내부 속성을 수정할 수 있는지 뜻하는 속성
    속성값이 true면 delete 연산자로 그 프로퍼티를 제거할 수 있으며 프로퍼티가 가진 내부 속성을 수정할 수 있다.


프로퍼티 디스크립터

프로퍼티 디스크립터는 프로퍼티의 속성 값을 뜻하는 객체이다.
객체가 가진 프로퍼티 이름은 프로퍼티가 가진 속성 이름과 같다.


// 데이터 프로퍼티의 프로퍼티 디스크립터
{
	value: 프로퍼티의 값,
    writable: 논리값,
    enumerable: 논리값,
    configurable: 논리값  
}

// 접근자 프로퍼티의 프로퍼티 디스크립터
{
	get: getter함수값,
    set: setter함수값,
    enumerable: 논리값,
    configurable: 논리값  
}



프로퍼티 디스크립터 가져오기: Object.getOwnPropertyDescriptor


// 첫 번째 인수는 객체의 참조고 두 번째 인수는 프로퍼티의 이름을 뜻하는 문자열이다.
var tom = { name: "Tom"};
Object.getOwnPropertyDescriptor(tom, "name");
// {value: "Tom", writable: true, enumerable: true, configurable: true}

// 프로토타입으로 상속받은 프로퍼티나 없는 프로퍼티를 지정하면 undefined를 반환한다.
Object.getOwnPropertyDescriptor({}, "name");  // undefined
Object.getOwnPropertyDescriptor(tom, "toString"); // undefined



객체의 프로퍼티 설정하기: Object.defineProperty

객체의 프로퍼티에 프로퍼티 디스크립터를 설정한다.
첫 번째 인수: 객체의 참조, 두번째 인수: 프로퍼티의 이름을 뜻하는 문자열,
세 번째 인수: 프로퍼티 디스크립터의 참조


// 실행 후에는 수정한 객체의 참조를 반환한다.
var obj = {};
Object.defineProperty(obj, "name", {
  value: "Tom",
  writable: ture,
  enumerable: false,
  configurable: true
});
Object.getOwnPropertyDescriptor(obj, "name");
// {value: "Tom", writable: true, enumerable: false, configurable: true}



객체의 프로퍼티 속성 여러 개를 한번에 설정하기: Object.defineProperties

객체가 가진 프로퍼티 여러 개에 각각의 프로퍼티 디스크립터를 설정한다.
첫 번째 인수: 객체의 참조, 두 번째 인수: 새롭게 설정, 변경하고자 하는 프로퍼티 이름이 키로 지정된 프로퍼티가 여러 개 모인 객체
실행 후에는 수정된 객체의 참조를 반환한다.


var person = Object.defineProperties({},{
    _name: {
      value: "Tom",
      writable: true,
      enumerable: true,
      configurable: true
    },
    name: {
      get: function(){ return this._name; },
      set: function(value){
        var str = value.charAt(0).toUpperCase() + value.substring(1);
        this._name = str;
      },
      enumerable: true,
      configurable: true
    }
});
Object.getOwnPropertyDescriptor(person, "name");
// {enumerable: true, configurable: true}




프로퍼티 유무

in 연산자

객체 안에 지명한 프로퍼티가 있는지 검색하며, 그 검색 대상은 그 객체가 소유한 프로퍼티와 상속받은 프로퍼티 모두이다.


var person = {name : "Tom"};
console.log("name" in person);  // true : 이 객체가 소유한 프로퍼티
console.log("age" in person);  // false : 프로퍼티가 없음 
console.log("toString" in person);  // true : person은 toString을 상속받았음

hasOwnProperty 메서드

지명한 프로퍼티가 그 객체가 소유한 프로퍼티면 true을 반환하고 상속 받은 프로퍼티면 false를 반환한다.


var person = {name : "Tom"};
console.log(person.hasOwnProperty("name")); // true : 이 객체가 소유한 프로퍼티
console.log(person.hasOwnProperty("toString")); // false : 상속받은 프로퍼티 

propertyIsEnumerable 메서드

지정한 프로퍼티가 그 객체가 소유한 프로퍼티이며 열거할 수 있을 때 true 반환


var person1 = {name : "Tom", age: 17}
var person2 = Object.create(person1);
person2.name = "Huck";
console.log(person2.propertyIsEnumerable("name"));  // true : 이 객체가 소유한 열거 가능 프로퍼티
console.log(person2.propertyIsEnumerable("age"));  // false : 상속받은 프로퍼티
console.log(Object.prototype.propertyIsEnumerable("toString"));  // false : 열거할 수 없는 프로퍼티




프로퍼티 열거

for/in 문

객체와 객체의 프로토타입 체인에서 열거할 수 있는 프로퍼티를 찾아내어 꺼내는 반복문이다.
Object.prototyped의 프로퍼티는 열거할 수 없으므로 for/in문으로는 찾아낼 수 없다.


var person1 = {name: "Tom", age: 17};
var person2 = Object.create(person1);
person2.name = "Huck";
for(var p in person2) console.log(p); // name, age... 순서대로 표시됨 

Object.keys 메서드

지정한 객체가 소유한 프로퍼티 중에서 열거할 수 있는 프로퍼티 이름만 배열로 만들어서 반환한다.
해당 객체가 소유한 프로퍼티 이름만 조회하는 용도로 Object.keys 메서드가 적합하다.


var group = {groupName : "Tennis circle"};
var person = Object.create(group);
person.name = "Tom";
person.age = 17;
person.sayHello = function(){console.log("Hello! " + this.name)};
Object.defineProperty(person,"sayHello",{enumerable : false});
console.log(Object.keys(person)); // ["name", "age"]


Object.getOwnPropertyNames 메서드

인수로 지정한 객체가 소유한 프로퍼티 이름을 배열로 만들어서 반환한다.
그때 열거할 수 있는 프로퍼티와 열거할 수 없는 프로퍼티의 이름을 모두 배열로 만든다.
Object.keys 메서드는 열거할 수 없는 프로퍼티인 sayHello는 열거하지 않았지만 getOwnPropertyNames 메서드는 열거할 수 없는 프로퍼티까지 모두 열거한다.


console.log(Object.getOwnPropertyNames(person));
// ["name", "age", "sayHello"]


JSON

자바스크립트 객체를 문자열로 표현하는 데이터 포맷이다. JSON을 통해 객체를 직렬화할 수 있다.
직렬화는 컴퓨터의 메모리 속에 있는 객체를 똑같은 객체로 환원할 수 있는 문자열로 변환하는 과정을 말한다.

표기방법

JSON 포맷은 자바스크립트의 리터럴 표기법에 기반을 두고 있으며 자바스크립트 리터럴 표기법의 부분 집합이다.
JSON 데이터는 그 전체를 작은 따옴표로 묶은 문자열이다.
객체의 프로퍼티 이름은 큰 따옴표로 묶는 문자열로 표기한다.

데이터 타입표기 예설명
숫자12.345정수와 부동소수점의 10진수 표기만 가능하다.
부동 소수점은 지수 표기법도 사용할 수 있다.
문자열"abc"큰따옴표로 묶어야 한다. 이스케이프 시퀀스도 포함할 수 있다.
논리값truetrue 또는 false
null 값null-
배열[1, "abc", true]모든 데이터 타입을 배열의 요소로 사용할 수 있다.
객체{"x": 1 "y": "abc"}프로퍼티 이름은 큰 따옴표로 묶는 문자열로 표기한다.

// 객체 리터럴
{name : "Tom", age: 17, marriage: false, data: [2, 5, null]};

// JSON 데이터로 변환
'{"name" : "Tom", "age" : 17, "marriage": false, "data": [2, 5, null]}'

JSON의 변환과 환원

자바스크립트 객체를 JSON 문자열로 변환하기 : JSON.stringify

JSON.stringify(value[, replacer[, space]])
인수로 받은 객체를 JSON 문자열로 바꾸어 반환한다.
첫 번째 인수 : value에는 JSON으로 변환할 객체를 지정한다.
두 번째 인수 : replacer는 함수 또는 배열을 지정한다.
함수를 지정하면 문자열로 만드는 프로퍼티와 키와 값을 함수의 인수로 받아서 프로퍼티 값을 표현하는 문자열을 반환하고 배열을 지정하면 배열의 요소로 객체의 프로퍼티 이름을 필터링한다.
세 번째 인수 : space에는 출력하는 문자열을 구분할 때 사용할 공백 문자를 지정한다.


JSON.stringify({}); // '{}'
JSON.stringify(3.14); // '3.14'
JSON.stringify("abc"); // '"abc"'
JSON.stringify(true); //  'true'
JSON.stringify([2, 4, null]); // '[2, 4, null]'
JSON.stringify({x:1, y:2}); //  {"x":1, "y":2}

// 배열로 지정
JSON.stringify({x:1, y:2, z:3}, ["x","z"]);	// '{"x":1, "z":3}'

JSON 문자열을 자바스크립트 객체로 환원하기 : JSON.parse

JSON.parse(text[, reviver])
인수로 받은 문자열을 자바스크립트 객체로 환원해서 반환한다.
첫 번째 인수 : text는 자바스크립트의 객체로 환원하고자 하는 JSON 문자열을 지정한다.
두 번째 인수 : 프로퍼티의 키와 값을 인수로 받는 함수를 지정할 수 있다.


// 첫 번째 인수만 지정한 기본 동작
JSON.parse('{}');	//{}
JSON.parse('3.14');	// 3.14
var 0 = {name: "Tom", age: 17, marriage: false, data: [2, 5, null]};
var s = JSON.stringify(o);
// '{"name": "Tom", "age": 17, "marriage": false, "data": [2, 5, null]}'
var p = JSON.parse(s);
// {name: "Tom", age: 17, marriage: false, data: [2, 5, null]}




profile
다재다능한 코린이가 될거야 ! 🧚‍♀️

0개의 댓글