지적 코딩을 위한 매우 얕은 지식

Javascript/Js

JS 객체(2)

toy2508 2022. 6. 1. 22:20
반응형

1.  프로퍼티 삭제

    - delete 연산자를 통해서 객체에서 프로퍼티를 삭제
    - 자체 프로퍼티만 삭제할 뿐 상속된 프로퍼티는 삭제 하지 않는다.
    - 상속된 프로퍼티를 삭제하려면 반드시 해당 프로퍼티를 정의한 프로토타입 객체에서 삭제해야함

    - delete는 변경 가능 속성이 false 인 프로퍼티는 제거하지 않는다.
      (내장 객체의 일부 프로퍼티, 변수 선언이나 함수 선언으로 생성된 전역 개체의 프로퍼티는 변경 불가)
    - 변경 불가인 프로퍼티를 삭제하려면 Type Error 발생(strict 모드인 경우)

let obj = {x: 1}; // obj에는 자체 프로퍼티 x가 있고 toString을 상속
delete obj.x; // --> true 반환 : 프로퍼티 x를 삭제
delete obj.x; // --> true 반환 : x가 존재하지 않으므로 아무 일도 일어나지 않는다.
delete obj.toString; // --> true 반환 : toString은 자체 프로퍼티가 아니므로 아무 일도
                                       일어나지 않는다.
delete 1; // --> true


// 다음은 일반 모드의 결과이며, 스트릭트 모드에서는 모든 TypeError 발생
delete Object.prototype;  // --> flase 반환 : 프로퍼티 변경 불가

var x = 1; // 전역 변수 선언
delete globalThis.x; // --> false 반환 : 해당 프로퍼티는 삭제 불가

function f() {}     // 전역함수 선언
delete glbobalThis.f;  // --> false 반환 : 삭제 불가

globalThis.x = 1; // 변경 가능한 프로퍼티 생성(let, var는 불가)
delete x // --> true : 이 프로퍼티를 삭제 가능(스트릭트 모드에서 SyntaxError 발생)
delete globalThis.x // 명시적으로 전역 객체를 참조해야 동작

 

2. 프로퍼티 테스트

    -  주어진 이름을 가진 프로퍼티가 존재하는지 확인이 필요할 때,
       in 연산자, hasOwnProperty(), propertyIsEnumerable() 메서드를 사용

let obj = {x:1};

// in : 왼쪽 프로퍼티 이름이 오른쪽 객체에 자체프로퍼티 
        이거나 상속된 프로퍼티로 존재하는지 체크
"x" in obj // --> true 반환 : obj에는 자체 프로퍼티 x가 있음
"y" in obj // --> false 반환 : obj에는 프로퍼티 y가 없음
"toString" in obj // --> true 반환 : obj는 toString을 상속함

// hasOwnProperty : 주어진 이름을 가진 자체 프로퍼티가 있는지 체크
obj.hasOwnProperty("x")  // --> true 반환 : obj에는 자체 프로퍼티 x가 존재
obj.hasOwnProperty("y")  // --> false 반환 : obj에는 프로퍼티 y가 없음
obj.hasOwnProperty("toString") // --> false 반환 : toString은 상속된 프로퍼티임

// propertyIsEnumerable() : 자체 프로퍼티에 존재하면서 열거 가능 속성인지 체크
obj.propertyIsEnumerable("x") // --> true 반환: obj에는 열거 가능 프로퍼티 x가 존재
obj.propertyIsEnumerable("toString") // --> false 반환: 자체 프로퍼티 x
Object.prototype.propertyIsEnumerable("toString") // --> false : 열거 불가


// in과 동일한 기능을 하는 !== 사용하기도 함
obj.x !== undefined  // --> true 반환: obj에는 프로퍼티 x가 있음
obj.y !== undefined  // --> false 반환: obj에는 프로퍼티 y가 없음
obj.toString !== undefined // --> true 반환: obj에는 toString을 상속

 

3. 프로퍼티 열거

 - for/in 루프는 상속 여부 구분하지 않고 열거 가능한 프로퍼티를 순회 한다.
   다만, 객체가 상속하는 내장 메서드는 열거 불가이다.

let obj = {x:1, y:2, z:3};  // 열거 가능한 자체 프로퍼티 세개
obj.propertyIsEnumerable("toString") // --> false: 열거 불가
for(let p in obj) { // 프로퍼티 순회
 	console.log(p) // x,y,z를 출력하지만 toString은 아님
}

// 상속된 프로퍼티가 열거되는 것을 막을 때는 다음과 같이 루프 바디 안에서
// 명시적으로 체크한다

for (let p in obj) {
	if(!obj.hasOwnProperty(p)) continue; // 상속된 프로퍼티 건너뜀
}

for (let p in obj) {
	if(type obj[p] === "function") continue; // 메서드는 건너뜀
}

 - 프로퍼티 이름을 배열로 저장할 수 있는 함수 
    1) Object.keys() : 객체의 열거 가능한 자체 프로퍼티 이름을 배열로 반환
                               (열거 불가 프로퍼티, 상속된  프로퍼티, 이름이 심벌인 프로퍼티 제외)
    2) Object.getOwnPropertyNames() : 이름이 문자열이기만 하면 열거 불가인 자체 프로퍼티
                                                              이름도 배열로 반환
    3) Object.getOwnPropertySymbols() :  열거 가능 여부를 따지지 않고 이름이 심별인 자체 
                                                                  프로퍼티 배열 반환
    4) Reflect.owneKeys() : 열거 가능 여부, 문자열/심벌 여부와 상관없이 자체 프로퍼티
                                          이름 전체 배열 반환

 - 프로퍼티 열거 순서
    1) 이름이 음이 아닌 정수인 문자열 프로퍼티가 첫 번째로 나열되며 작은 수에서
        큰 수 순으로 열거된다. 따라서 배열 및 배열 비슷한 객체의 프로퍼티도 순서대로 열거된다.
    2) 배열 인덱스와 비슷한 프로퍼티를 모두 열거한 다음에는 음수나 부동 소수점 숫자처럼 보이는
        프로퍼티를 포함해 이름이 문자열인 프로퍼티를 열거한다. 이 프로퍼티는 객체에 추가된 순서
        대로 열거된다. 객체 리터럴로 정의된 프로퍼티는 리터럴에 쓰인 순서를 따른다.
    3) 마지막으로, 이름이 심벌인 프로퍼티를 객체에 추가된 순서대로 열거된다.

 

4. 객체 확장

 - 특정 객체의 프로퍼티를 다른 객체의 프로퍼티로 복사하는 행위

// 기본 복사 방법
let target = {x:1}, source = {y:2, z:3}
for(let key of Object.keys(source)) {
	target[key] = source[key];
}


// Object.assing 으로 복사하는 방법
Object.assign({}, defaults, obj); 
// 객체를 새로 생성하고 기본 값을 복사한 다음, 
// 이 기본 값을 obj의 프로퍼티로 덮어 쓴다.

// 분해 연산자 사용하여 복사하는 방법(*)
o = {...defaluts, ...o};


// Object.assign()과 마찬가지이지만 기존 프로퍼티는 덮어 쓰지 않는다.
// 심벌 프로퍼티를 복사하지 않는 것과 같다.
function merge(target, ...source) {
	for(let source of sources) {
    	for(let key of Object.keys(source)) {
        	if(!(key in target) { //Object.assign과 다른 점임
            	target[key] = source[key];
            }
        }
    }
    return target;
}

Object.assign({x:1}, {x:2, y:2}, {y:3, z:4})  // --> {x:2,y:3,z:4}
merge({x:1}, {x:2, y:2}, {y:3, z:4})          // --> {x:1,y:2,z:4}
반응형

'Javascript > Js' 카테고리의 다른 글

JS 배열(1)  (0) 2022.06.06
JS 객체(3)  (0) 2022.06.05
JS 객체(1)  (0) 2022.05.29
JS 점프문  (0) 2022.05.28
JS 반복문  (0) 2022.05.25