위리윗
632
2019-11-05 18:03:05
8
330

javascript 다차원 객체 선언


안녕하세요

javascript에서 다차원 객체를 선언하고 안에 값을 넣으려하니 자꾸만 해당 객체를 찾지 못하는 오류가 발생하고 있습니다.

예시는 아래와 같습니다.

- 선언 부

var root = {
    A: {}
};

var A= {
a: '',
b: '',
c: '',
B: {}
};

var B= {
d: '',
e: '',
f: '',
g: ''
};


- data 삽입

root.A.a = "data";
root.A.b = "data";
root.A.c = "data";
root.A.B.d = "data";
root.A.B.e = "data";
root.A.B.f = "data";
root.A.B.g = "data";


이때 노란 표시가 된 객체 안의 객체 안의 객체 안의 필드에 data를 넣으려니 해당 필드를 참조하지 못하고 있습니다.

이에 B.d = "data"; 형식으로 test해보니 참조하는것을 확인하였습니다.

어느 부분을 살펴봐야할지 감이 오질 않아 질문 올려봅니다.

시간 남으시는 선배님들 조언 부탁드립니다.

0
0
  • 답변 8

  • 초코쪼꼬
    6k
    2019-11-05 18:15:49

    음.. root.A는 선언이 되어 있다치고


    root.A에 a라는 하위를 파서 'data' 넣는다.. 뭐 좋아요.

    root.A가 하위에 B라는 값이 없는데 그 바로 밑에 d를 생성한다..?


    그냥 오류죠. 하위가 없기 때문에


    추가로 


    var root = {
        A: {}
    };


    이것과 


    var A= {
    a: '',
    b: '',
    c: '',
    B: {}
    };
    
    var B= {
    d: '',
    e: '',
    f: '',
    g: ''
    };


    이것은 왜 선언 해둔건가요?

    0
  • 위리윗
    632
    2019-11-05 19:27:00

    초코쪼꼬

    안녕하세요.

    먼저 시간 내주셔서 감사합니다.

    먼저 제가 javascript 문법에 대한 지식이 많이 부족하여 정확한 설명을 드리기는 어려울 것 같습니다.

    root.A가 하위에 B라는 값이 없는데 그 바로 밑에 d를 생성한다..?

    그냥 오류죠. 하위가 없기 때문에 ]

    root 구조체의 필드로는 A라는 구조체가 있다.

    A라는 구조체의 필드로는 문자열 변수 a, b, c와 구조체 B가 있다.

    이에 이 부분에 대해서는 아래와 같은 소스코드로 값이 들어감을 확인 하였습니다.

    그 다음 질문에 대해서도 같은 답이 되리라 생각합니다.

    var A = {
    	b: '',
    	B: {}
    };
    
    var B= {
    	C: {}
    };
    
    var C= {
        c: '',
        d: '',
        e: '',
        f: '',
    };
    
    A.B.c = "data";
    A.B.d = "data";
    A.B.e = "data";
    A.B.f = "data";
    0
  • digda
    80
    2019-11-05 20:06:14 작성 2019-11-05 20:08:28 수정됨

    js는 정적 타입 언어가 아닙니다.

    일단 모든 것이 객체입니다.

     B: {} 부분을 B라는 구조체 타입을 선언했다는 의미로 쓰셨겠지만

    실제로 저건 A라는 객체에 속한 'B'라는 이름의 프로퍼티를 추가한 것일 뿐입니다.

    그 프로퍼티 값이 빈 오브젝트인 것이고요.


    작성하신 var A 와 var B, var C는 지금 서로 아무 관계도 없습니다.

    서로간의 참조가 없어요. 때문에 기대했던 동작이 나오지 않습니다.


    위에서 [하위가 없다]는 답변도 이와 같은 맥락입니다.


    기존 정적 타입 언어와는 다름은 인지하시고

    다른 시각으로 접근해 보시는 길 권해드립니다.

    0
  • 위리윗
    632
    2019-11-05 20:32:43 작성 2019-11-05 20:42:33 수정됨

    digda

    안녕하세요

    시간내주어 답변 달아주셔서 감사합니다.

    말씀해주신 부분에 대해서는 이해가 가질 않습니다.

    말씀해주신 대로라면 제가 댓글에 첨부한 예시에서도 B와 C를 참조하지 못하여야는게 맞는것 아닌가요..?

    실제 data가 들어간 것을 확인한 것과 같은예시는 아래와 같습니다.

    var A = {
    	b: '',
    	B: {}
    };
    
    var B= {
            a: '',
            b: '',
            c: '',
    	C: {}
    };
    
    var C= {
        d: '',
        e: '',
        f: '',
    };
    
    A.B.c = "data";
    A.B.d = "data";
    A.B.e = "data";
    A.B.f = "data";

    아래는 객체명 및 변수, data를 가린 디버그 화면 입니다.


    위와 같은 결과들이 있다보니 말씀해주신

    [작성하신 var A 와 var B, var C는 지금 서로 아무 관계도 없습니다.

    서로간의 참조가 없어요. 때문에 기대했던 동작이 나오지 않습니다.]

    가 이해가 되질 않습니다... ㅠㅠ


    - 내용 추가

    구조체 C의 멤버 선언을 구조체 B안에서 하였을 때 해결이 되지 않았었습니다.

    이에 구조체 B의 멤버 선언까지 구조체 A안에서 해주었을 때 일단 문제는 해결할 수 있었습니다.

    다만 두분께서 말씀해주신 부분과 제가 작성한 [ 구조체 A안의 구조체 B안의 멤버에 data insert 성공 ] 이 서로 대립된다고 생각되어 이해가 잘 가지 않습니다.

    또한 이렇게 해결할 경우 가독성 뿐만 아니라 중복 작성이 3가지 정도가 나오게 되기 때문에 정확한 원인을 알고 싶습니다.

    0
  • digda
    80
    2019-11-05 21:12:02 작성 2019-11-05 21:13:06 수정됨
    var A = {
    	b: '',
    	B: {} // 빈 객체
    };

    이미 이 시점에 A 객체 안에 B라는 이름은 가진 속성에 [빈 객체]가 선언/할당 되었으므로

    A.B 로 접근 가능합니다.


    A.B.c 라고 접근 또한 가능합니다.

    자바스크립트는 이 'c' 를 미리 명시하지 않아도 접근했을 때 에러가 발생하지 않습니다.

    컴파일러가 미리 타입을 lookup하고 메모리를 확보하는 단계는 거치지 않습니다. 런타임에 결정되죠.

    다만 console.log(A.B.c)는 undefined가 나올겁니다. 선언하고 할당한 값이 없으니까요.


    A.B.c = "data"; 를 해 봅시다.

    자바스크립트에서는 이 상황을 객체 확장이라고 부릅니다.

    그냥... 기존 객체에 하나의 레퍼런스를 추가하는 것이라고 생각하면 됩니다.

    그리고 그 확장이라는건 모든 객체에서 가능합니다.


    이해가 되지 않는다는 부분에 대해서는

    하나하나 검증을 해 보실 필요가 있을 텐데요.

    위 상황에서 그럼 var B, var C를 빼고도 

    A.B.c = "data";
    A.B.d = "data";
    A.B.e = "data";
    A.B.f = "data";

    이 코드가 동작하는지 확인해 보세요.

    아마 var B, var C 가 있든 없든 똑같이 접근 가능할거고

    이 말인 즉슨, var B, var C는 var A와는 전혀 상관없는 독립적인 선언이라는걸 확인하실 수 있을겁니다.


    구조체라는... 개념을 가지고 계속 그 기준으로 생각하시면 이해가 힘드실 듯 합니다.

    기존 배경 지식으로 가지고 계신 구조체와 비슷해 보이지만

    특성은 많이 다릅니다. 아예 다른 것이라 생각해도 무방해요.


    의도하신 객체를 만들려면

    var A = {
        b: ''
    };
    
    var B= {
        a: '',
        b: '',
        c: ''
    };
    
    var C= {
        d: '',
        e: '',
        f: ''
    };
    
    A.B = B;
    B.C = C;


    혹은

    var A = {
        b: '',
        B: {
            a: '',
            b: '',
            c: '',
            C: {
                d: '',
                e: '',
                f: ''
            }
        }
    };

    이거면 충분합니다.


    0
  • 위리윗
    632
    2019-11-06 10:56:35

    digda

    답답하실텐데 답변 달아주셔서 정말 감사합니다.

    [위 상황에서 그럼 var B, var C를 빼고도] 부분을 아래 코드와 같이 테스트 해보았습니다.

    var A{
         B: {}
    }
    ---
    1. A.B.id = "data";
    2. A.B.type = "data";
    3. A.B.C.json = "data";

    1, 2번은 정상 동작하면서 말씀해주신 독립적인 객체와 객체 확장이란 것을 충분히 이해하였습니다.

    하지만 3번은 undefined가 출력되었습니다. 이에 [javascript문법에서 객체의 일반 멤버 확장은 가능하다. 하지만 객체의 객체 멤버에 대한 확장은 불가능하다.]로 이해를 하였고 자바스크립트 객체의 객체멤버 확장에 대해서 찾아보고 있습니다.

    또한 발생하였던 문제점과 제가 말씀드린 코드의 가독성과 중복 작성에 대해서는 말씀해주신대로

    A.B = B;

    B.C = C;
    로 해결을 하였습니다.

    0
  • jjmean2
    280
    2019-11-07 08:56:54 작성 2019-11-07 08:57:37 수정됨

    var team = {   manager: { } }

    이건 team이라는 변수에

    {
      manager: { }
    }

    라는 객체를 생성해서 할당한 것입니다.

    그리고 다음 줄에 새로 다음과 같이 정의한다고 해보면

    var manager = {
      id: 30,
      name: 'John'
    }

    이건 manager라는 변수에 

    {
      id: 30,
      name: 'John'
    }

    이라는 객체를 생성해서 할당하는 것입니다.

    그런데 뒤에 정의한 manager라는 변수는 앞에 정의한 team.manager 라는 프로퍼티와는 이름만 같지 아무 상관이 없습니다. 따라서 team.manager.id 로 찾아서는 30을 얻을 수 없습니다. 마찬가지로 team.manager.id에 어떤 값을 넣는다고 해도 manager.id 가 바뀌지는 않습니다. 

    var root = {
        A: {}
    };
    
    var A= {
    a: '',
    b: '',
    c: '',
    B: {}
    };
    
    var B= {
    d: '',
    e: '',
    f: '',
    g: ''
    };

    여기에서 root.A와 A, A.B와 B는 전혀 별개의 객체라는 것입니다.

    시도하신 것 중에

    root.A.B.d = 'data'

    이 있었는데 이것은 에러가 납니다. 그런데 

    root.A.a = 'data' 

    는 에러가 나지 않습니다. 이유를 살펴보려면 프로퍼티를 하나하나 따라가 봅시다.

    root.A는 { }, 즉 빈 객체입니다. 자바스크립트에서 객체는 임의의 프로퍼티에 접근해도 에러가 아닙니다. 정의되지 않은 프로퍼티에 접근하면 undefined를 반환할 뿐입니다. hashmap/dictionary에서 존재하지 않는 키로 접근할 때와 성질이 비슷합니다.

    즉, root.A.a, root.A.b, root.A.anykey 전부 에러가 아닙니다. 물론 빈 객체이니 모두 결과는 undefined가 나옵니다. 마찬가지로 임의의 프로퍼티에 세팅하는 것도 가능합니다. 즉, root.A.a = 'data'는  root.A 라는 빈 객체에 'a'라는 프로퍼티를 만들고 거기에 'data'를 값으로 세팅하는 것입니다. 

    그럼 에러 케이스를 봅시다. root.A.B는 root.A에 없는 프로퍼티인 B로 접근하고 있으니 undefined입니다. 그럼 root.A.B.d는 (undefined).d 와 마찬가지가 됩니다. undefined 는 객체가 아닙니다. undefined의 프로퍼티에 접근하려는 시도는 에러로 취급됩니다. 따라서 이 문장은 에러가 되는 것입니다.

    마지막 댓글에서 

    A.B.C.json = 'data'

    는 에러입니다. A.B.C가 undefined이기 때문입니다. 

    A.B.C = {}
    A.B.C.json = 'data'

    이런 식으로 A.B.C에 뭐라도 집어넣어주고 했으면 에러 없이 동작했을 것입니다.

    0
  • 위리윗
    632
    2019-11-07 13:59:29

    jjmean2

    이해가 잘 되었습니다.

    설명해주셔서 감사합니다!!!!!!!

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.