JS 객체

Yun Young Choi·2022년 4월 18일
6

Javascript

목록 보기
1/7
post-thumbnail

자바스크립트 객체

자바스크립트에서 객체란?

  • 객체(Object)기반 스크립트 언어, 자바스크립트를 이루는 거의 "모든" 것이 객체
  • 원시 타입(Primitives)을 제외한 나머지 값(함수, 배열, 정규표현식 등)은 모두 객체 = 다양한 값을 담음

자바스크립트 객체

  • key(키), value(값)으로 구성된 프로퍼티(property)의 집합
  • 프로퍼티의 값으로 자바스크립트에서 사용할 수 있는 모든 값 사용 가능
  • 자바스크립트 함수는 일급 객체이므로 값으로 취급 가능
  • 프로퍼티 값으로 함수 사용 가능!
  • 프로퍼티 값이 함수면 일반 함수와 구분하기 위해 "메소드"라 부름

자바스크립트 객체는 객체지향의 상속을 구현하기 위해
프로토타입(prototype)이라고 부르는 객체의 프로퍼티와 메소드를 상속받을 수 있다.


프로퍼티

프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 symbol(원시 자료형) 값
프로퍼티 값 : 모든 값

※규칙※

  1. 프로퍼티 키에 문자열이나 symbol 값 이외의 값이 들어가면 암묵적 타입 변환으로 "문자열"이 됨
  2. 이미 존재하는 프로퍼티에 키를 중복 선언하면 새로 선언된 프로퍼티가 기존 프로퍼티를 덮어씀
  3. 배열과는 달리 객체는 프로퍼티를 열거할 때 순서를 보장하지 않음!

메소드

프로퍼티 값이 함수일 경우, 일반 함수와 구분하기 위해 메소드라 부름
즉, 메소드는 객체에 제한되어 있는 함수를 의미


객체 생성


//객체 리터럴 문법 = 객체 선언 시 주로 객체 리터럴 사용

var user = new Object();

    // {} 내에 아무것도 기술하지 않으면 빈 객체 생성
    var user = {};

    var person = {
        name : 'Choi',
        gneder : 'femail',
        sayHi : function() {
            console.log(`Hi!`);
        }
    };

    console.log(person);
    //{name: 'Choi', gneder: 'femail', sayHi: ƒ}

    person.sayHi();
    //Hi!

Object 생성자 함수

  • new 연산자와 object 생성자 함수를 호출하여 빈 객체 생성 가능
  • 빈 객체 생성 이후 프로퍼티 또는 메소드를 추가하여 <객체 완성>

  • 생성자(constructor) 함수란 new 키워드와 함게 객체를 생성하고 초가화하는 함수를 말함
    생성자를 통해 생성된 객체를 인스턴스(Instance)라고 함
  • 자바스크립트는 Object 함수 이외에도 String, Number, Boolean, Array, Date, RegExp 등의 빌트인 생성자 함수를 제공
  • 일반 함수와 생성자 함수를 구분하기 위해 생성자 함수의 이름은 파스칼 케이스(PascalCase)를 사용함

//빈 객체 생성
    var person2 = new Object();

    //프로퍼티 추가
    person2.name = 'Choi';
    person2.gender = 'female';

    person2.sayHi = function() {
        console.log('Hi! My name is ' + this.name);
    };
    
    console.log(typeof person2); //object
    console.log(person2);       //{name: 'Choi', gender: 'female', sayHi: ƒ}

this


알면 좋은 것

Object 생성자 함수를 사용해 빈 객체를 생성해야 하는 것은 아님!
객체 생성법은 리터럴을 사용하는 것을 권장.

사실 객체 리터럴 방식으로 생성된 객체는
결국 빌트인 함수인 Object 생성자 함수로 객체를 생성하는 것을 단순화시킨 축약 표현


생성자 함수

  • 객체 리터럴 방식과 Object 생성자 함수 방식으로 객체를 생성하는 것은 프로퍼티 값만 다른 여러 개의 객체를 생성할 때 불편함
  • 동일한 프로퍼티를 갖는 객체임에도 불구하고 매번 같은 프로퍼티를 기술해야 하는 불편함
    var person3 = {
        name : 'Choi',
        gender : 'female',
        sayHi : function() {
            console.log('Hi! i am ' + this.name);
        }
    };

    var person4 = {
        name : 'Kim',
        gender : 'female',
        sayHi : function() {
            console.log('Hi! i am' + this.name);
        }
    };

    //생성자 함수를 사용하며 마치 객체를 생성하기 위한 템플릿(클래스)처럼 사용하여
    //프로퍼티가 동일한 객체 여러개를 간편하게 사용할 수 있다.

    //생성자 함수
    function Person(name, gender) {
        this.name = name;
        this.gender = gender;
        this.sayHi = function() {
            console.log('Hi i am ' + this.name);
        };
    }

    //인스턴스 생성
    var person1 = new Person('Kim', 'male');
    var person2 = new Person('Lee', 'feamle');

    console.log('person1 : ', typeof person1);
    console.log('person2 : ', typeof person2);
    console.log('person1 : ', person1);
    console.log('person2', typeof person2);

    person1.sayHi();
    person2.sayHi();

  1. 생성자 함수 이름은 일반적으로 대문자로 시작
    (생성자 함수임을 인식하도록 도움)
  2. 프로퍼티 또는 메소드명 앞에 기술한 this는 생성자 함수가 생성할 인스턴스(Instance)를 가리킴
  3. this에 연결(바인딩)되어 있는 프로퍼티와 메소든느 public(외부 참조가능)하다.
  4. 생성자 함수 내에서 선언된 일반 변수는 private(외부 참조 불가능)하다.
    (즉, 생성자 함수 내부에서는 자유로운 접근이 가능하나 외부에서는 접근 불가)

객체 프로퍼티 접근

프로퍼티 키

  • 프로퍼티 키는 일반적으로 문자열(빈 문자열 포함)을 지정
  • 프로퍼티 키에 문자열이나 symbol 값 이외의 값을 지정하면 암묵적 형변환으로 "문자열"이 됨
  • 또한 무자열 타입의 값으로 수렴될 수 있는 표현식도 가능
  • 프로퍼티 키는 문자열이므로 따옴표 사용

  • 자바스크립트의 사용 가능한 유효한 이름인 경우, 따옴표 생략 가능
  • 반대로 생각하면 사용 불가한 유효한 이름인 경유, 따옴표 생략 불가

프로퍼티 값은 모든 값과 표현식이 올 수 있으며 프로퍼티값이 함수인 경우 이를 메소드라고 한다.


    var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        1: 10,
        function: 1 // OK. 하지만 예약어는 사용하지 말아야 한다.
        };

        console.log(person);

    //프로퍼티 키 first-name에는 반드시 따옴표를 사용해야 하지만 first_name에는 생략 가능
    // '-' 연산자가 있는 표현식이기 때문에

    var person = {

    first-name: 'Ung-mo', // SyntaxError: Unexpected token -

    };

    var person = {

        [first-name]: 'Ung-mo', // ReferenceError: first is not defined

        };

    //예약어를 프로퍼티 키로 사용하여도 에러가 발생하지 않는다. 하지만 예상치 못한 에러가 발생할 수 있으므로
    //예약어를 프로퍼티 키로 사용하면 안됨!

    /* 자바스크립트 예약어
        abstract  arguments boolean break byte
    case  catch char  class*  const
    continue  debugger  default delete  do
    double  else  enum* eval  export*
    extends*  false final finally float
    for function  goto  if  implements
    import* in  instanceof  int interface
    let long  native  new null
    package private protected public  return
    short static  super*  switch  synchronized
    this  throw throws  transient true
    try typeof  var void  volatile
    while with  yield
    // *는 ES6에서 추가된 예약어
    */

프로퍼티 값 찾기

  • 객체의 프로퍼티 값에 접근하는 법은 마침표(.) 표기법과 대괄호([]) 표기법이 있다.
 var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        1: 10
        };

        console.log(person);

        //유효하지 않은 이름이기 때문에 따옴표 쓰고 대괄호([])로 접근
        //대괄호로 접근시 문자열로!!!!
        console.log(person.first-name);    // NaN: undefined-undefined
        console.log(person[first-name]);   // ReferenceError: first is not defined
        console.log(person['first-name']); // 'Ung-mo'

        //유효한 이름이기 때문에 따옴표 생략하고 마침표(.)로 접근
        console.log(person.gender);    // 'male'
        console.log(person[gender]);   // ReferenceError: gender is not defined
        console.log(person['gender']); // 'male'

        //유효하지 않은 이름이기 때문에 따옴표 쓰고 대괄호([])로 접근
        //대괄호로 접근시 문자열로!!!!
        console.log(person['1']); // 10
        console.log(person[1]);   // 10 : person[1] -> person['1']
        console.log(person.1);    // SyntaxError

    //프로퍼티 이름이 유효한 자바스크립트 이름이 아니거나 예약어인 경우, 프로퍼티 값은 대괄호 표기법 사용
    //대괄호 표기법 사용시, 대괄호 내에 들어가는 프로퍼티 이름은 반드시 문자열이어야 한다.

    //객체에 존재하지 않는 프로퍼티를 참조하면 undefined
    
    var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        };

        console.log(person.age); // undefined

프로퍼티 값 갱신

  • 객체가 소유하고 있는 프로퍼티에 새로운 값을 할당하면 값 갱신
 var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        };

        person['first-name'] = 'Kim';
        console.log(person['first-name'] ); // 'Kim'

프로퍼티 동적 생성

  • 객체가 소유하고 있지 않는 프로퍼티 키에 값을 할당하면 주어진 키와 값으로 프로퍼티를 생성하여 객체에 추가
    var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        };

        person.age = 20;
        console.log(person.age); // 20

프로퍼티 삭제

  • delete 연산자를 사용하여 객체 프로퍼티 삭제 가능, 피연산자는 '프로퍼티 키'이어야 함!
    var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male',
        };

        delete person.gender;
        console.log(person.gender); // undefined

        delete person;
        console.log(person); // Object {first-name: 'Ung-mo', last-name: 'Lee'}

for-in 문

for-in문은 객체의 문자열 키를(key)를 순회하기 위한 문법이다. 배열에는 사용하지 않는 것을 권장.

  1. 객체의 경우, 프로퍼티 순서 보장 X
    • why! 프로퍼티에는 순서 없다.
    • 배열은 순서를 보장하는 데이터 구조이지만 객체와 마찬가지로 순서 보장 X
  2. 배열 요소들만 순회하지 않는다.
    var person = {
        'first-name': 'Ung-mo',
        'last-name': 'Lee',
        gender: 'male'
        };

    // prop에 객체의 프로퍼티 이름이 반환된다. 단, 순서는 보장되지 않음
    for (var prop in person) {
        console.log(prop + ': ' + person[prop]);
        }

    /*
    first-name: Ung-mo
    last-name: Lee
    gender: male
    */

    var array = ['one', 'two'];

    // index에 배열의 경우 인덱스가 반환됨
    for (var index in array) {
        console.log(index + ': ' + array[index]);
    }

    /*
    0: one
    1: two
    */

for-of 문

const array = [1, 2, 3];
        array.name = 'my array';


    for (const value of array) {
        console.log(value);
    }

    /*
    1
    2
    3
    */

    for (const [index, value] of array.entries()) {
        console.log(index, value);
    }

    /*
    0 1
    1 2
    2 3
    */

for–in 문은 객체의 프로퍼티를 순회하기 위해 사용하고
for–of 문은 배열의 요소를 순회하기 위해 사용한다.


Pass-by-reference

  • Object type을 객체 타입 또는 참조 타입이라고 함

  • 참조 타입 : 객체의 모든 연산이 실제 값이 아닌 - 참조값으로 처리

  • 원시 타입 : 값이 한 번 정해지면 변경할 수 없음 (immutable)

객체는 프로퍼티 변경, 추가, 삭제가 되므로 변경 가능(mutable)한 값이라 할 수 있음

따라서 객체 타입은 동적으로 변할 수 있으므로 어느 정도 메모리 공간을 확보해야 하는지 예측할 수 없음.
런타입에 메모리 공간을 확보하고 메모리의 힙 영역(Heap Segment)에 저장.

이에 반대로 원시 타입은 값(value)으로 전달, 즉, 복사되어 전달

 // Pass-by-reference
    var a = [1, 2, 3];
    var b = a;

    a[0] = 10000
    console.log(b);

    //b의 결과는 [10000,2, 3]이 됨
    //이유 : 값을 복사하여 새로운 메모리에 저장한 것이 아닌 a의 주소 참조
    // >>> pass-by-reference

Pass-by-value

  • 원시 타입은 값(value)로 전달. 즉, 값이 복사되어 전달(값에 의한 전달)
  • 원시 타입은 값이 한 번 정해지면 변경 X (immutable)
    -런타임(변수 할당 시점)에 메모리의 스택 영역(Stack Segment)에 고정된 메모리에 저장
     // Pass-by-value
     var a = 10;
     var b = a;

    //b에 10이라는 값 할당, 메모리에 새로운 공간에 10이라는 값 저장
    //만약 a에 다른 값을 재할당해도 b에 영향 X
    // >>> pass-by-value

profile
안냥하세요

2개의 댓글

comment-user-thumbnail
2022년 4월 19일

멋있읍니다.~

답글 달기
comment-user-thumbnail
2022년 5월 2일

완전. 좋은 정보 감사합니다~^^
아래 블로그도 좋은 글이 많더라구요. 구경오세요.^^
https://velog.io/@chm0202

답글 달기