ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript - 객체
    개발언어/JavaScript 2022. 12. 22. 14:15

    JavaScript 객체를 만드는 방법

    let user = new Object(); // '객체 생성자 '문법
    let user = {}; //'객체 리터럴 문법'

    중괄호{...}를 이용해서 객체를 선언하는 것을 객체 리터럴(object literal)이라고 부른다. 객체를 선언할 때 주로 이방법을 사용한다.

     

    리터럴과 프로퍼티


    delete 연산자

    delete 연산자를 사용하면 프로퍼티를 삭제할 수 있다.

    delete user.age;


    여러 단어를 조합해 프로퍼티 이름을 만든 경우엔 프로퍼티 이름에 따옴표로 묶어 주어야 한다.

    let user = {
    	name:"John",
        age: 30,
        "likes birds": true //복수의 단어는 따옴표로 묶어야 한다.
    };

    상수 객체는 수정될 수 있다.

    const로 선언된 객체는 수정 될 수 있다.

    const user = {
    	name: "John"
    };
    
    user.name = "Pete";
    
    alert(user.name); //Pete

    const는 user의 속성 갯수와 종류를 고정하지만 속성의 value를 고정하지는 않습니다.


    대괄호 표기법

    여러 단어를 조합해 프로퍼티 키를 만든 경우엔, 점 표기법을 사용해 프로퍼티 값을 읽을 수 없습니다.

    //문법 에러가 발생합니다.
    user.like birds = true

    자바스크립트는 위와 같은 코드를 이해하지 못합니다. user.like까지는 이해하다가 예상치 못한 birds를 만나면 문법에러를 뱉어 냅니다.

     

    '점'은 키가 '유효한 변수 식별자 '인 경우에만 사용할 수 있다. 유효한 변수 식별자엔 공백이 없어야 합니다. 또한 숫자로 시작하지 않아야 하며 $_를 제외한 특수 문자가 없어야 합니다.

     

    키가 유효한 식별자가 아닌 경우엔 점 표기법 대신에 '대괄호 표기법(square bracket notation)'이라 불리는 방법을 사용할 수 있습니다. 대괄호 표기법은 키에 어떤 문자열이 있던지 상관없이 동작한다.

    let user ={};
    
    //set
    user["like birds"] = true;
    
    //get
    alert(user["likes birds"]); // true
    
    //delete
    delete user["likes birds"];

    대괄호 표기법 안에서 문자열을 사용할 땐 문자열을 따옴표로 묶어줘야한다.

     

    대괄호 표기법을 사용하면 아래 예시에서 변수를 키로 사용한 것과 같이 문자열 뿐만 아니라 모든 표현식의 평가 결과를  프로퍼티 키로 사용할 수 있다.

    let key = "like birds";
    
    //user["likes birds"] = true; 와 같다.
    user[key] = true;

    변수 key는 런타임에 평가되기 때문에  사용자 입력값 변경 등에 따라 값이 변경될 수 있다. 어떤 경우든, 평가가 끝난 이후의 결과가 프로퍼티 키로 사용된다.

    let user = {
    	name:"John",
        age:30
    };
    
    let key = prompt("사용자의 어떤 정보를 얻고 싶으신가요?","name");
    
    // 변수로 접근
    alert(user[key]); John (프롬프트 창에 "name"을 입력한 경우)

     

    다음과 같은 방식으로 는 사용지 불가능하다.

    let user = {
    	name:"John",
        age:30
    }
    
    let key = "name";
    alert(user.key) //undefined

    계산된 프로퍼티

    객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러 싸여있는 경우, 이를 계산된 프로퍼티(computed property)라고 부른다.

    let fruit = prompt("어떤 과일을 구매하시겠습니까?","apple");
    
    let bag ={
    	[fruit]: 5, //변수 fruit에서 프로퍼티 이름을 동적으로 받아 옵니다.
    };
    
    alert(bag.apple); //fruit에 "apple"이 할당되었다면, 5가 출력됩니다.

    위 예시에서 [fruit]는 프로퍼티 이름을 변수 fruit에서 가져오겠다는 것을 의미한다. 사용자가 프롬프트 대화상자에 apple을 입력했다면 bag엔 {apple : 5}가 할당되었을 것이다.

     

    let fruit = prompt("어떤 과일을 구매하시겠습니까?","apple");
    let bag = {};
    
    //변수 fruit을 사용해 프로퍼티 이름을 만들었습니다.
    bag[fruit] = 5;

    두 방식중 계산된 프로퍼티를 사용한 예시가 더 깔끔해 보인다.

     

    한편, 다음 예시처럼 대괄호 안에는 복잡한 표현식이 올 수도 있다.

    let fruit = 'apple';
    
    let bag = {
    	[fruit + 'Computers']: 5 //bag.appleComputers =5
    };

    대괄호 표기법은 프로퍼티 이름과 값의 제약을 없애주기 때문에 점 표기법보다 훨씬 강력하다. 그런데 작성하기 번거롭다는 단점이 있다.

    이런 이유로 프로퍼티 이름이 확정된 상황이고, 단순한 이름이라면 점 표기법을 사용하다가 뭔가 복잡한 상황이 발생했을 때 대괄호 표기법으로 바꾸는 경우가 있다.


    프로퍼티 이름의 제약사항

    let obj = {
    	0 : "test" // "0" : "test"와 동일하다.
    }
    
    // 숫자 0은 문자열 "0"으로 변환되기 때문데 두 alert창은 값은 프로퍼티에 접근한다.
    alert( obj["0"] ); //test
    alert( obj[0] ); //test (동일한 프로퍼티)

     

    이와같이 객체 프로퍼티 키에 쓸 수 있는 문자열엔 제약이 없지만, 역사적인 이유 때문에 특별 대우를 받는 이름이 하나 있다.

    바로,__proto__입니다.

    let obj ={};
    obj.__proto__ = 5; 숫자를 할당한다.
    alert(obj.__proto__); //[object Object] - 숫자를 할당했지만 값은 객체가 되었다.

    원시값 5를 할당했는데 무시된 것을 확인할 수 있다.

     


    'in' 연산자로 프로퍼티 존재 여부 확인하기

    자바스크립트 객체의 중요한 특징 중 하나는 다른 언어와 달리, 존재하지 않은 프로퍼티에 접근하려 해도 에러가 발생하지 않고 undefined를 반환한다는 것이다.

    let user = {};
    alert(user.noSuchProperty === undefined); // true는 '프로퍼티가 존재하지 않음'을 의미

    이렇게 undefined와 비교하는 것 이외에도 연산자 in을 사용하면 프로퍼티 존재 여부를 확인할 수 있다.

    "key" in object
    let user = {name:"John", age:30};
    
    alert("age" in user); //user.age가 존재하므로 true가 출력된다.
    alert("blabla" in user); //user.blabla는 존재지 않기 때문에 flase가 출력된다.

    in 왼쪽엔 반드시 프로퍼티 이름이 와야한다. 프로퍼티 이름은 보통 따옴표로 감싼 문자열이다.

     

    따옴표를 생략하면 아래 예시와 같이 엉뚱한 변수가 조사 대상이된다.

    let user = { age : 30};
    let key = "age";
    alert( key in user); //true, 변수 key에 저장된 값("age")을 사용해 프로퍼티 존재 여부를 확인한다.

    대부분 일치 연산자를 사용해서 프로퍼티 존재 여부를 알아내는 방법("=== undefinde")은 꽤 잘 동작한다. 그런데 프로퍼티는 존재하는데, 값에 undefined가 할당한 경우 일치연산자가 잘 동작하지 않을 수 있다.

    let obj = {
    	test: undefined
    }
    
    alert(obj.test); // 값이 'undefined'이므로, alert 창에 undefined가 출력된다. 그런데 프로퍼티 test는 존재한다.
    alert("test" in obj); // 'in'을 사용하면 프로퍼티 유무를 제대로 확인할 수 있다.(true가 출려된다.)

     

    undefined는 변수는 정의되어 있으나 값이 할당되지 않은 경우에 쓰기 때문에 프로퍼티 값이 undefined인 경우 흔치않다. 값을 '알 수 없거나(unknown)' 값이 '비어 있다는(empty)'것을 나타낼 때는 주로 null을 사용한다.


     

    객체 정렬 방식

    객체와 객체 프로퍼티를 다루다보면"프로퍼티엔 순서가 있을까?" 라는 의문이 생기기 마련이다. 반복문은 프로퍼티를 추가한 순서대로 실행될지, 그리고 이 순서는 할상 동일할지 궁금해진다.

     

    답은 간단하다. 객체는 '특별한 방식으로 정렬 된다.' 정수 프로퍼티(integer property)는 자동으로 정렬되고, 그외의 프로퍼티는 객체에 추가한 순서 그대로 정렬된다.

    let codes = {
    	"49":"독일",
        	"41":"스위스",
        	"44":"영국",
       	 //..,
        	"1":"미국"
    };
    
    for (let code in codes){
    	alert(code); //1,41,44,49
    }

    현재 개발 중인 애플리케이션의 주 사용자가 독일인이라고 가정해 봅시다. 나라 번호를 선택하는 화면에서 49가 맨 앞에 오도록 하는 게 좋을 것이다.

     

    그런데 코드를 실행해 보면 예상과 전혀 다름 결과가 출력된다.

    • 미국(1)이 첫번째로 출력된다.
    • 그 뒤로 스위스(41),영국(44),독일(49)이 차례대로 출력된다.

    이유는 나라 번호(키)가 정수이어서 1,41,44,49 순으로 프로퍼티가 자동정렬되었기 때문이다.

     

    💡정수 프로퍼티가 무엇일까?
    '정수 프로퍼티'라는 용어는 변형 없이 정수에서 왔다 갔다 할 수 있는 문자열을 의미한다.

    문자열"49"는 정수로 변환하거나 변환한 정수를 다시 문자열로 바꿔도 변형이 없기 때문에 정수 프로퍼티이다. 하지만 '+49'와 '1.2'는 정수 프로퍼티가 아니다.

    Math.trunc()

    반올림하지 않고 숫자의 정수 부분만을 표시하는 메서드

    alert(String(Math.trunc(Number("49"))) );
    // '49'가 출력된다. 기존에 입력한 값과 같으므로 정수 프로퍼티이다.
    alert(String(Math.trunc(Number("+49"))) );
    // '49'가 출력된다. 기존에 입력한 값(+49)와 다르므로 정수 프로퍼티가 아니다.
    alert(String(Math.trunc(Number("1.2"))) );
    // '1'가 출력된다. 기존에 입력한 값(1.2)와 다르므로 정수 프로퍼티가 아니다.

     

    한편, 키가 정수가 아닌 경우엔 작성된 순서대로 프로퍼티가 나열된다.

    let user = {
    	name:"John",
        surname:"Smith"
    };
    user.age = 25; //프로퍼티를 하나 추가한다.
    
    //정수 프로퍼티가 아닌 프로퍼티는 추가된 순서대로 나열된다.
    for(let prop in user){
    	alert(prop); //name,surname,age
    }

     

    위 예시에서 49(독일 나라 번호)를 가장 위에서 출력되도록 하려면 나라 번호가 정수로 취급되지 않도록 속임수를 쓰면된다.

    각 나라 번호 앞에 "+"를 붙인다.

    let codes = {
    	"+49":"독일",
        	"+41":"스위스",
        	"+44":"영국",
       	 //..,
        	"+1":"미국"
    };
    
    for (let code in codes){
    	alert(code); //49,41,44,1
    }

     


    정리

    객체는 몇 가지 특수한 기능을 가진 연관 배열(associative array)이다.

    • 프로퍼티 키는 문자열이나 심볼이어야 한다. 보통은 문자열이다.
    • 값은 어떤 자료현도 가능한다.

    [출처 - https://ko.javascript.info/object]

    댓글

Designed by Tistory.