JavaScript Property

Property의 값을 가져오려면

  • . 연산자 : 연산자 우측에 Property 이름 "식별자"
  • [] 연산자 : 연산자 우측에 Property이름의 "문자열 표현식"

Property 값 생성

        var temp = {}
        console.log(temp);

        temp.newProperty = "a";
        temp["new Property"] = "b";

        console.log(temp);

output:

연관 배열로서의 객체

temp.newProperty : 식별자가 와야 함 -> 코딩할 때 fix됨.
temp.["new Property"] : 표현식을 인자로 받음 -> 프로그램 실행중 입력받은 것 사용 가능

        function addName(nameList, name, studentNumber) {
            nameList["name"] = studentNumber
        }
        // 이런 코드가 동작 한다는 뜻!

상속

객체에서 Property를 찾을 때, 고유 Property안에 찾고자 하는 Property가 없으면,
상속받은 Prototype 객체에서 해당 Property를 찾는다.

        function inherit(p) {
            if (p == null) throw TypeError();
            if (Object.create) // ECMAScript 5 이상에 정의되어 있음
                return Object.create(p);
        }

        var o = {};
        o.x = 1;
        var p = inherit(o); // 객체 o와 Object.prototype를 상속받는 객체
        p.y = 2;
        var q = inherit(p); // 객체 p와 o, Object.prototype을 상속받는 객체.
        q.z = 3;
        var s = q.toString(); // q 는 Object.prototype을 상속받았기 때문에 toString 사용가능

        var result = q.x + q.y; // 값은 3 
        console.log(result);

Output :

상속받은 Prototype Property를 바꾸고 싶을 때

상속받은 Property 가 read only 라면 수정 불가.
그렇지 않다면 두 가지 경우의 수

  • 고유 Property로 재정의 된다. // 기본
  • Prototype Property 의 값이 재설정된다. // setter method가 정의되어있을 경우

Property 접근 에러

존재하지 않는 Property에 접근하는 경우

  • 에러 발생하지 않음. -> undefined return

존재하지 않는 객체의 Property에 접근하는 경우

  • 에러 발생
        var temp2 = o.a;
        console.log(temp2) // undefined
        var length = o.a.length; // undefined에서 Property를 찾으려 해서 error

Output :

에러 방지

        var len = temp2 && temp2.a && temp2.length

객체 o에 Property p를 설정할 수 없는 경우

  • p가 o의 고유 Property이고 readonly일 경우
    • 읽기전용 Property p 에는 값 설정할 수 없다.
  • p가 상속된 Property 이고 readonly일 경우
    • 동일한 이름의 고유 Property로 감출 수 없음.
  • p가 고유 Property도, 상속받은 Property도 아닌데 extensible 속성이 false일 경우.

프로퍼티 삭제하기

delete 연산자. Property의 값이 아니라 Property 자체를 지움

delete book.author;
delete book["main title"];
  • delete 연산자는
    • 고유 프로퍼티만 지울 수 있다.
    • 삭제에 성공, 프로퍼티가 존재하지 않아 영향을 미치지 못한 경우, return true를 한다.
o = {x:1}
delete o.x; // 삭제 성공 return true
delete o.x; // 존재하지 않아 return true
delete o.toString; // 고유프로퍼티가 아니라 아무일도 안일어나고 true
delete 1; // 말도 안 되지만 return true
* configurable 속성이 false 인 프로퍼티는 지우지 않는다.

아래는 nonreconfigurable

        delete Object.prototype; // 지울 수 없음
        var x = 1;
        delete this.x; // 지울 수 없음
        function f() {}
        delete this.f; // 지울 수 없음

프로퍼티 검사

주어진 이름의 프로퍼티가 있는지 검사할 필요가 있을 때

  • in 연산자
  • hasOwnProperty()
  • propertyIsEnumerable() : 추가적으로 enumerable 속성까지 true여야
  • 단순히 Property에 접근
        var oo = {x : 1};
        console.log("x" in oo);
        console.log("y" in oo);
        console.log("toString" in oo);

        console.log(oo.hasOwnProperty("x"));
        console.log(oo.hasOwnProperty("y"));
        console.log(oo.hasOwnProperty("toString"));

        var ooo = inherit({y : 2});
        ooo.x = 1;
        console.log(ooo.propertyIsEnumerable("x")); // 고유 프로퍼티 열거 가능 -> true
        console.log(ooo.propertyIsEnumerable("y")); // 상속받은 프로퍼티 -> false
        console.log(ooo.propertyIsEnumerable("toString")); // 내장프로퍼티, 열거불가능 -> false

Output:

!== 와 === 연산자

  • undefined 와 null 을 구분할 수 있음.

프로퍼티 열거하기

for / in loop

        var o = {x:1, y:2, z:3};
        for(p in o) {
            console.log(p, o[p]);
        }

Output :

상속받은 Property 생략, method 생략

        for(p in o) {
            if(!o.hasOwnProperty(p))
                continue;
        }

        for(p in o) {
            if(typeof o[p] === "function")
                continue;
        }

프로퍼티 Getter / Setter

ECMAScript 5 에서는 Property의 값을 getter / setter method로 대체할 수 있음.
단순히 값을 값는 "Data Property" 와 다른 "Accessor Property" 라고 한다.

  • 프로그램이 객체의 Accessor Property에 접근하면 getter method의 반환 값이 Property 접근 표현식의 값이 됨.
  • 프로그램이 객체의 Accessor Property의 값을 바꾸려고 하면 getter method가 실행된다. = 오른쪽의 값이 method의 인자로 전달된다.

getter / setter 존재 유무로 읽기전용, 쓰기전용 결정.
특이한 것 : setter 만 있으면 쓰기전용. read 하려고 하면 있음에도 undefined return

Accessor Property의 정의

        var oo = {
            // Data Property
            data_prop: value,
            get accessor_prop() { /* 함수 몸체 */},
            set accessor_prop(value) { /* 함수 몸체 */ }
        }

Example : 2차원 좌표와 극좌표를 가지는 Property

        var p = {
            x: 1.0,
            y: 1.0,
            get r() {
                return Math.sqrt(this.x*this.x + this.y*this.y);
            },
            set r(newValue) {
                console.log("in setter : ", newValue);
                var oldValue = Math.sqrt(this.x*this.x + this.y*this.y);
                var ratio = newValue / oldValue;
                this.x *= ratio;
                this.y *= ratio;
                console.log("now x : ", this.x);
                console.log("now y : ", this.y);
            },

            get theta() {
                return Math.atan2(this.y, this.x);
            }
        }

        var q = inherit(p);
        q.x = 1; q.y = 1;
        console.log(q.r);
        console.log(q.theta);
        q.r = 777
        console.log(q.r);
        console.log(q.theta);

Output

Example : 일련번호 생성

        var serialnum = {
            $n: 0, // 프로퍼티 이름의 $는 private 프로퍼티라는 힌트

            get next() {return this.$n++;},
            set next(n) {
                if(n>=this.$n) this.$n++;
                else throw "serial number can only be set to a larger value";
            }
        }

Property 속성

이름, 값, 그리고 속성

  • value
    • 데이터 프로퍼티의 값도 속성으로 본다.
  • writeable
    • 값 변경 가능 여부
  • enumerable
    • 열거가능 여부
  • configurable
    • 3가지 속성 변경 가능한지.

Property의 3가지 속성 값을 질의하고 설정할 수 있도록 하는 ECMAScript 5 API

라이브러리 만들 때 중요

  1. 프로토타입 객체에 method 추가 , 추가된 method를 내장 method처럼 열거할 수 없게 만들기 위해
  2. 변경, 삭제 불가한 프로퍼티를 정의, 객체를 고정(lock down) 시키기 위해

접근자 Property의 속성 표현 위해 Property descriptor라는 객체 사용.

데이터 Property의 Property descriptor

  • value, writeable, enumerable, configurable 등의 Property를 가짐

접근자 Property의 Property descriptor

  • get, set, enumerable, configurable

객체의 특정 Property에 대한 Property descriptor객체
-> Object.getOwnPropertyDescriptor() 를 통해 얻을 수 있음.

        console.log(Object.getOwnPropertyDescriptor({x:1}, "x"));

          // 없는 Property거나 상속받은 Property 는 undefined
        console.log(Object.getOwnPropertyDescriptor({}, "x"));
        console.log(Object.getOwnPropertyDescriptor({}, "toString"));

Output

getOwnPropertyDescriptor 는 고유 프로퍼티만 검사 가능.
상속된 프로퍼티를 검사하고 싶으면 프로토타입 chain을 명시적으로 순회해야함.

프로퍼티의 속성 설정, 임의의 속성으로 새 프로퍼티를 만들기 위해

Object.defineProperty()

        console.log(o);
        Object.defineProperty(o, "x", {value : 1,
                                        writeable: true,
                                        enumerable: false,
                                        configurable: true})
        console.log(Object.getOwnPropertyDescriptor(o, "x"));

Output

동시에 여러개

        var p = Objet.defineProperties({}, {
            x: {value:1, writeable: true, enumerable:true, configurable: true},
            y: {value:1, writeable: true, enumerable:true, configurable: true},
            r: {get: function() {
                return Math.sqrt(this.x*this.x + this.y*this.y);
            },
            writeable: true,
            configurable: true}
        })

객체 속성

모든 객체는 prototype, class, extensible 속성을 가지고 있음.

Extensible 속성

객체에 새 프로퍼티를 추가할 수 있는지 여부
목적 : 잠겨있는 객체의 상태를 고정, 외부에서 변경하는 것을 막는 것.

객체 직렬화

  • JSON.stringify()
  • JSON.parse()

'웹 프로그래밍 > Javascript' 카테고리의 다른 글

Javascript Function  (0) 2020.06.24
Javascript Scope, 변수  (0) 2020.06.23
Javascript Array  (0) 2020.06.23
JavaScript Object 생성  (0) 2020.06.19
Javascript 세미콜론  (0) 2020.05.30

+ Recent posts